Skip to content
This repository
Browse code

0.5 release

  • Loading branch information...
commit eeb334036eb9e52849d6a81275105970843d6524 1 parent 346f253
authored July 04, 2007
2  CurrentVersion.txt
... ...
@@ -1,2 +1,2 @@
1  
-0.4
  1
+0.5
2 2
 20070605
BIN  Releases/0.5/Texter Installer 0.5.exe
Binary file not shown
63  Releases/0.5/TexterInstaller.ahk
... ...
@@ -0,0 +1,63 @@
  1
+#SingleInstance,Force 
  2
+#NoEnv
  3
+#NoTrayIcon
  4
+Goto,DIRECTORY
  5
+
  6
+DIRECTORY:
  7
+InstallDir = 
  8
+Gui, Add, Text,y10 x10,Where would you like to install Texter?
  9
+Gui, Add, Edit, x20 y30 r1 W300 vInstallDir,%A_ProgramFiles%\Texter
  10
+Gui, Add, Button,w80 GBrowse x320 y29,&Browse
  11
+Gui, Add, Button,w80 default GInstall x225 yp+50,&Install
  12
+Gui, Add, Button,w80 xp+90 GCancel,&Cancel
  13
+Gui, Show, auto,Install Texter
  14
+RETURN
  15
+
  16
+BROWSE:
  17
+FileSelectFolder, InstallDir,,1,Select your installation folder
  18
+if ErrorLevel = 0
  19
+	GuiControl,,InstallDir,%InstallDir%
  20
+RETURN
  21
+
  22
+INSTALL:
  23
+Gui, Submit
  24
+Gui,Destroy
  25
+;MsgBox,%InstallDir%
  26
+IfNotExist,%InstallDir%
  27
+	FileCreateDir,%InstallDir%
  28
+Process,Exist,texter.exe
  29
+if ErrorLevel != 0
  30
+	Process,Close,texter.exe
  31
+FileInstall,texter.exe,%InstallDir%\texter.exe,1
  32
+if ErrorLevel = 0
  33
+{
  34
+	;MsgBox Problem!
  35
+	Gui, Add, Text,y10 x10,Texter successfully installed!
  36
+	Gui, Add, Checkbox, Checked y30 x20 vLaunch, Launch Texter
  37
+	Gui, Add, Button,w80 default GAutoRun x300 yp+65,&Finish
  38
+	Gui, Show, auto,Installation complete
  39
+}
  40
+;MsgBox, Installed
  41
+
  42
+return
  43
+
  44
+AUTORUN:
  45
+Gui,Submit
  46
+Gui,Destroy
  47
+if Launch = 1
  48
+{
  49
+	;MsgBox, Launch
  50
+	Run,%InstallDir%\texter.exe
  51
+	;MsgBox,Ran: %InstallDir%\texter.exe
  52
+}
  53
+
  54
+Goto,Exit
  55
+return
  56
+
  57
+CANCEL:
  58
+Gui, Destroy
  59
+Goto,Exit
  60
+return
  61
+
  62
+EXIT:
  63
+ExitApp
1,374  Releases/0.5/texter.ahk
... ...
@@ -0,0 +1,1374 @@
  1
+; Texter
  2
+; Author:         Adam Pash <adam@lifehacker.com>
  3
+; Gratefully adapted several ideas from AutoClip by Skrommel:
  4
+;		http://www.donationcoder.com/Software/Skrommel/index.html#AutoClip
  5
+; Huge thanks to Dustin Luck for his contributions
  6
+; Script Function:
  7
+;	Designed to implement simple, on-the-fly creation and managment 
  8
+;	of auto-replacing hotstrings for repetitive text
  9
+;	http://lifehacker.com/software//lifehacker-code-texter-windows-238306.php
  10
+SetWorkingDir %A_ScriptDir%
  11
+#SingleInstance,Force 
  12
+#NoEnv
  13
+StringCaseSense On
  14
+AutoTrim,off
  15
+SetKeyDelay,-1
  16
+SetWinDelay,0 
  17
+Gosub,UpdateCheck
  18
+Gosub,ASSIGNVARS
  19
+Gosub,READINI
  20
+EnableTriggers(true)
  21
+Gosub,RESOURCES
  22
+Gosub,TRAYMENU
  23
+Gosub,BuildActive
  24
+;Gosub,AUTOCLOSE
  25
+
  26
+FileRead, EnterKeys, %EnterCSV%
  27
+FileRead, TabKeys, %TabCSV%
  28
+FileRead, SpaceKeys, %SpaceCSV%
  29
+;Gosub,GetFileList
  30
+Goto Start
  31
+
  32
+START:
  33
+EnableTriggers(true)
  34
+hotkey = 
  35
+executed = false
  36
+Input,input,V L99,{SC77}
  37
+input:=hexify(input)
  38
+IfInString,ActiveList,%input%|
  39
+{ ;input matches a hotstring -- see if hotkey matches a trigger for hotstring
  40
+	if hotkey in %ignore%
  41
+	{
  42
+		StringTrimLeft,Bank,hotkey,1
  43
+		StringTrimRight,Bank,Bank,1
  44
+		Bank = %Bank%Keys
  45
+		Bank := %Bank%
  46
+		if input in %Bank%
  47
+		{
  48
+			GoSub, EXECUTE
  49
+			executed = true
  50
+		}
  51
+	}
  52
+}
  53
+if executed = false
  54
+{
  55
+	SendInput,%hotkey%
  56
+}
  57
+Goto,START
  58
+return
  59
+
  60
+EXECUTE:
  61
+WinGetActiveTitle,thisWindow ; this variable ensures that the active Window is receiving the text, activated before send
  62
+;; below added b/c SendMode Play appears not to be supported in Vista 
  63
+EnableTriggers(false)
  64
+if (A_OSVersion = "WIN_VISTA") or (Synergy = 1) ;;; need to implement this in the preferences - should work, though
  65
+	SendMode Input
  66
+else
  67
+	SendMode Play   ; Set an option in Preferences to enable for use with Synergy - Use SendMode Input to work with Synergy
  68
+if (ExSound = 1)
  69
+	SoundPlay, %ReplaceWAV%
  70
+ReturnTo := 0
  71
+hexInput:=Dehexify(input)
  72
+StringLen,BSlength,hexInput
  73
+Send, {BS %BSlength%}
  74
+FileRead, ReplacementText, %A_ScriptDir%\Active\replacements\%input%.txt
  75
+StringLen,ClipLength,ReplacementText
  76
+
  77
+IfInString,ReplacementText,::scr::
  78
+{
  79
+	;To fix double spacing issue, replace `r`n (return + new line) as AHK sends a new line for each character
  80
+	StringReplace,ReplacementText,ReplacementText,`r`n,`n, All
  81
+	StringReplace,ReplacementText,ReplacementText,::scr::,,
  82
+	IfInString,ReplacementText,`%p
  83
+	{
  84
+		textPrompt(ReplacementText)
  85
+	}
  86
+	IfInString,ReplacementText,`%s
  87
+	{
  88
+		StringReplace, ReplacementText, ReplacementText,`%s(, ¢, All
  89
+		Loop,Parse,ReplacementText,¢
  90
+		{
  91
+			if (A_Index != 1)
  92
+			{
  93
+				StringGetPos,len,A_LoopField,)
  94
+				StringTrimRight,sleepTime,A_LoopField,%len%
  95
+				StringMid,thisScript,A_LoopField,(len + 2),
  96
+				Sleep,%sleepTime%
  97
+				;WinActivate,%thisWindow%  The assumption must be made that in script mode
  98
+				; the user can intend to enter text in other windows
  99
+				SendInput,%thisScript%
  100
+			}
  101
+			else
  102
+			{
  103
+				;WinActivate,%thisWindow%  The assumption must be made that in script mode
  104
+				; the user can intend to enter text in other windows
  105
+				SendInput,%A_LoopField%
  106
+			}
  107
+		}
  108
+	}
  109
+	else
  110
+		SendInput,%ReplacementText%
  111
+	return
  112
+}
  113
+else
  114
+{
  115
+	;To fix double spacing issue, replace `r`n (return + new line) as AHK sends a new line for each character
  116
+	;(but only in compatibility mode)
  117
+	if MODE = 0
  118
+	{
  119
+		StringReplace,ReplacementText,ReplacementText,`r`n,`n, All
  120
+	}
  121
+	IfInString,ReplacementText,`%c
  122
+	{
  123
+		StringReplace, ReplacementText, ReplacementText, `%c, %Clipboard%, All
  124
+	}
  125
+	IfInString,ReplacementText,`%t
  126
+	{
  127
+		FormatTime, CurrTime, , Time
  128
+		StringReplace, ReplacementText, ReplacementText, `%t, %CurrTime%, All
  129
+	}
  130
+	IfInString,ReplacementText,`%ds
  131
+	{
  132
+		FormatTime, SDate, , ShortDate
  133
+		StringReplace, ReplacementText, ReplacementText, `%ds, %SDate%, All
  134
+	}
  135
+	IfInString,ReplacementText,`%dl
  136
+	{
  137
+		FormatTime, LDate, , LongDate
  138
+		StringReplace, ReplacementText, ReplacementText, `%dl, %LDate%, All
  139
+	}
  140
+	IfInString,ReplacementText,`%p
  141
+	{
  142
+		textPrompt(ReplacementText)
  143
+	}
  144
+	IfInString,ReplacementText,`%|
  145
+	{
  146
+		;in clipboard mode, CursorPoint & ClipLength need to be calculated after replacing `r`n
  147
+		if MODE = 0
  148
+		{
  149
+			MeasurementText := ReplacementText
  150
+		}
  151
+		else
  152
+		{
  153
+			StringReplace,MeasurementText,ReplacementText,`r`n,`n, All
  154
+		}
  155
+		StringGetPos,CursorPoint,MeasurementText,`%|
  156
+		StringReplace, ReplacementText, ReplacementText, `%|,, All
  157
+		StringReplace, MeasurementText, MeasurementText, `%|,, All
  158
+		StringLen,ClipLength,MeasurementText
  159
+		ReturnTo := ClipLength - CursorPoint
  160
+	}
  161
+
  162
+	if MODE = 0
  163
+	{
  164
+		if ReturnTo > 0
  165
+		{
  166
+			if ReplacementText contains !,#,^,+,{
  167
+			{
  168
+				WinActivate,%thisWindow%
  169
+				SendRaw, %ReplacementText%
  170
+				Send,{Left %ReturnTo%}
  171
+			}
  172
+			else
  173
+			{
  174
+				WinActivate,%thisWindow%
  175
+				Send,%ReplacementText%{Left %ReturnTo%}
  176
+			}
  177
+		}
  178
+		else
  179
+		{
  180
+			WinActivate,%thisWindow%
  181
+			SendRaw,%ReplacementText%
  182
+		}
  183
+	}
  184
+	else
  185
+	{
  186
+		oldClip = %Clipboard%
  187
+		Clipboard = %ReplacementText%
  188
+		if ReturnTo > 0
  189
+		{
  190
+			WinActivate,%thisWindow%
  191
+			Send,^v{Left %ReturnTo%}
  192
+		}
  193
+		else
  194
+		{
  195
+			WinActivate,%thisWindow%
  196
+			Send,^v
  197
+		}
  198
+		Clipboard = %oldClip%
  199
+	}
  200
+;	if ReturnTo > 0
  201
+;		Send, {Left %ReturnTo%}
  202
+
  203
+}
  204
+SendMode Event
  205
+IniRead,expanded,texter.ini,Stats,Expanded
  206
+IniRead,chars_saved,texter.ini,Stats,Characters
  207
+expanded += 1
  208
+chars_saved += ClipLength
  209
+IniWrite,%expanded%,texter.ini,Stats,Expanded
  210
+IniWrite,%chars_saved%,texter.ini,Stats,Characters
  211
+Return
  212
+
  213
+HOTKEYS: 
  214
+StringTrimLeft,hotkey,A_ThisHotkey,1 
  215
+StringLen,hotkeyl,hotkey 
  216
+If hotkeyl>1 
  217
+  hotkey=`{%hotkey%`} 
  218
+Send,{SC77}
  219
+Return 
  220
+
  221
+ASSIGNVARS:
  222
+Version = 0.5
  223
+EnterCSV = %A_ScriptDir%\Active\bank\enter.csv
  224
+TabCSV = %A_ScriptDir%\Active\bank\tab.csv
  225
+SpaceCSV = %A_ScriptDir%\Active\bank\space.csv
  226
+ReplaceWAV = %A_ScriptDir%\resources\replace.wav
  227
+TexterPNG = %A_ScriptDir%\resources\texter.png
  228
+TexterICO = %A_ScriptDir%\resources\texter.ico
  229
+StyleCSS = %A_ScriptDir%\resources\style.css
  230
+return
  231
+
  232
+READINI:
  233
+IfNotExist bank
  234
+	FileCreateDir, bank
  235
+IfNotExist replacements
  236
+	FileCreateDir, replacements
  237
+else
  238
+{
  239
+	IniRead,hexified,texter.ini,Settings,Hexified
  240
+	if hexified = ERROR
  241
+		Gosub,HexAll
  242
+}
  243
+IfNotExist resources
  244
+	FileCreateDir, resources
  245
+IfNotExist bundles
  246
+	FileCreateDir, bundles
  247
+IfNotExist Active
  248
+{
  249
+	FileCreateDir, Active
  250
+	FileCreateDir, Active\replacements
  251
+	FileCreateDir, Active\bank
  252
+}
  253
+IniWrite,%Version%,texter.ini,Preferences,Version
  254
+cancel := GetValFromIni("Cancel","Keys","{Escape}") ;keys to stop completion, remember {} 
  255
+ignore := GetValFromIni("Ignore","Keys","{Tab}`,{Enter}`,{Space}") ;keys not to send after completion 
  256
+IniWrite,{Escape}`,{Tab}`,{Enter}`,{Space}`,{Left}`,{Right}`,{Up}`,{Down},texter.ini,Autocomplete,Keys
  257
+keys := GetValFromIni("Autocomplete","Keys","{Escape}`,{Tab}`,{Enter}`,{Space}`,{Left}`,{Right}`,{Esc}`,{Up}`,{Down}")
  258
+otfhotkey := GetValFromIni("Hotkey","OntheFly","^+H")
  259
+managehotkey := GetValFromIni("Hotkey","Management","^+M")
  260
+MODE := GetValFromIni("Settings","Mode",0)
  261
+EnterBox := GetValFromIni("Triggers","Enter",0)
  262
+TabBox := GetValFromIni("Triggers","Tab",0)
  263
+SpaceBox := GetValFromIni("Triggers","Space",0)
  264
+ExSound := GetValFromIni("Preferences","ExSound",1)
  265
+Synergy := GetValFromIni("Preferences","Synergy",0)
  266
+
  267
+;; Enable hotkeys for creating new keys and managing replacements
  268
+if otfhotkey <>
  269
+{
  270
+	Hotkey,IfWinNotActive,Texter Preferences
  271
+	Hotkey,%otfhotkey%,NEWKEY	
  272
+	Hotkey,IfWinActive
  273
+}
  274
+if managehotkey <>
  275
+{
  276
+	Hotkey,IfWinNotActive,Texter Preferences
  277
+	Hotkey,%managehotkey%,MANAGE
  278
+	Hotkey,IfWinActive
  279
+}
  280
+
  281
+
  282
+;; This section is intended to exit the input in the Start thread whenever the mouse is clicked or 
  283
+;; the user Alt-Tabs to another window so that Texter is prepared
  284
+~LButton::Send,{SC77}
  285
+$!Tab::
  286
+{
  287
+	GetKeyState,capsL,Capslock,T
  288
+	SetCapsLockState,Off
  289
+	pressed = 0
  290
+	Loop {
  291
+		Sleep,10
  292
+		GetKeyState,altKey,Alt,P
  293
+		GetKeyState,tabKey,Tab,P
  294
+		if (altKey = "D") and (tabKey = "D")
  295
+		{
  296
+			if pressed = 0
  297
+			{
  298
+				pressed = 1
  299
+				Send,{Alt down}{Tab}
  300
+				continue
  301
+			}
  302
+			else
  303
+			{
  304
+				continue
  305
+			}
  306
+		}
  307
+		else if (altKey = "D")
  308
+		{
  309
+			pressed = 0
  310
+			continue
  311
+		}
  312
+		else
  313
+		{
  314
+			Send,{Alt up}
  315
+			break
  316
+		}
  317
+	}
  318
+	Send,{SC77}
  319
+	if (capsL = "D")
  320
+		SetCapsLockState,On
  321
+}
  322
+
  323
+$!+Tab::
  324
+{
  325
+	GetKeyState,capsL,Capslock,T
  326
+	SetCapsLockState,Off
  327
+	pressed = 0
  328
+	Loop {
  329
+		Sleep,10
  330
+		GetKeyState,altKey,Alt,P
  331
+		GetKeyState,tabKey,Tab,P
  332
+		GetKeyState,shiftKey,Shift,P
  333
+		if (altKey = "D") and (tabKey = "D") and (shiftKey = "D")
  334
+		{
  335
+			if pressed = 0
  336
+			{
  337
+				pressed = 1
  338
+				Send,{Alt down}{Shift down}{Tab}
  339
+				;Send,{Shift up}
  340
+				continue
  341
+			}
  342
+			else
  343
+			{
  344
+				continue
  345
+			}
  346
+		}
  347
+		else if (altKey = "D") and (shiftKey != "D")
  348
+		{
  349
+			pressed = 0
  350
+			Send,{Shift up}
  351
+			break
  352
+		}
  353
+		else if (altKey = "D") and (shiftKey = "D")
  354
+		{
  355
+			pressed = 0
  356
+			continue
  357
+		}
  358
+		else
  359
+		{
  360
+			Send,{Alt up}{Shift up}
  361
+			break
  362
+		}
  363
+	}
  364
+;	Send,{SC77}
  365
+	if (capsL = "D")
  366
+		SetCapsLockState,On
  367
+}
  368
+Return
  369
+
  370
+
  371
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Implementation and GUI for on-the-fly creation ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  372
+NEWKEY:
  373
+if A_GuiControl = + ;;;; MAYBE CHANGE THIS TO IfWinExist,Texter Management
  374
+	GuiControlGet,CurrentBundle,,BundleTabs
  375
+else
  376
+	CurrentBundle =
  377
+if (CurrentBundle != "") and (CurrentBundle != "Default")
  378
+	AddToDir = Bundles\%CurrentBundle%\
  379
+else
  380
+	AddToDir = 
  381
+Gui,1: Destroy
  382
+IniRead,EnterBox,texter.ini,Triggers,Enter
  383
+IniRead,TabBox,texter.ini,Triggers,Tab
  384
+IniRead,SpaceBox,texter.ini,Triggers,Space
  385
+Gui,1: font, s12, Arial  
  386
+Gui,1: +owner2 +AlwaysOnTop -SysMenu +ToolWindow  ;suppresses taskbar button, always on top, removes minimize/close
  387
+Gui,1: Add, Text,x10 y20, Hotstring:
  388
+Gui,1: Add, Edit, x13 y45 r1 W65 vRString,
  389
+Gui,1: Add, Edit, x100 y45 r4 W395 vFullText, Enter your replacement text here...
  390
+Gui,1: Add, Text,x115,Trigger:
  391
+Gui,1: Add, Checkbox, vEnterCbox yp x175 Checked%EnterBox%, Enter
  392
+Gui,1: Add, Checkbox, vTabCbox yp x242 Checked%TabBox%, Tab
  393
+Gui,1: Add, Checkbox, vSpaceCbox yp x305 Checked%SpaceBox%, Space
  394
+Gui,1: font, s8, Arial 
  395
+Gui,1: Add, Button,w80 x320 default,&OK
  396
+Gui,1: Add, Button,w80 xp+90 GButtonCancel,&Cancel
  397
+Gui,1: font, s12, Arial  
  398
+Gui,1: Add,DropDownList,x100 y15 vTextOrScript, Text||Script
  399
+Gui,1: Add,Picture,x0 y105,%TexterPNG%
  400
+Gui 2:+Disabled
  401
+Gui,1: Show, W500 H200,Add new hotstring...
  402
+return
  403
+
  404
+GuiEscape:
  405
+ButtonCancel:
  406
+Gui 2:-Disabled
  407
+Gui,1: Destroy
  408
+return
  409
+
  410
+ButtonOK:
  411
+Gui,1: Submit, NoHide
  412
+Gui 1:+OwnDialogs
  413
+hexRString:=hexify(RString)
  414
+IfExist, %A_ScriptDir%\%AddToDir%replacements\%hexRString%.txt
  415
+{
  416
+	MsgBox,262144,Hotstring already exists, A replacement with the text %RString% already exists.  Would you like to try again?
  417
+	return
  418
+}
  419
+IsScript := (TextOrScript == "Script")
  420
+
  421
+if SaveHotstring(RString, FullText, IsScript, AddToDir, SpaceCbox, TabCbox, EnterCbox)
  422
+{
  423
+	Gui 2:-Disabled
  424
+	Gui,1: Submit
  425
+}
  426
+Gosub,GetFileList
  427
+return
  428
+
  429
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; End Implementation and GUI for on-the-fly creation ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  430
+
  431
+
  432
+
  433
+TRAYMENU:
  434
+Menu,TRAY,NoStandard 
  435
+Menu,TRAY,DeleteAll 
  436
+Menu,TRAY,Add,&Manage hotstrings,MANAGE
  437
+Menu,TRAY,Add,&Create new hotstring,NEWKEY
  438
+Menu,TRAY,Add
  439
+Menu,TRAY,Add,P&references...,PREFERENCES
  440
+Menu,TRAY,Add,&Import bundle,IMPORT
  441
+Menu,TRAY,Add,&Help,HELP
  442
+Menu,TRAY,Add
  443
+Menu,TRAY,Add,&About...,ABOUT
  444
+Menu,TRAY,Add,&Disable,DISABLE
  445
+if disable = 1
  446
+	Menu,Tray,Check,&Disable
  447
+Menu,TRAY,Add,E&xit,EXIT
  448
+Menu,TRAY,Default,&Manage hotstrings
  449
+Menu,Tray,Tip,Texter
  450
+Menu,TRAY,Icon,resources\texter.ico
  451
+Return
  452
+
  453
+ABOUT:
  454
+Gui,4: Destroy
  455
+Gui,4: +owner2
  456
+Gui,4: Add,Picture,x200 y0,%TexterPNG%
  457
+Gui,4: font, s36, Courier New
  458
+Gui,4: Add, Text,x10 y35,Texter
  459
+Gui,4: font, s8, Courier New
  460
+Gui,4: Add, Text,x171 y77,%Version%
  461
+Gui,4: font, s9, Arial 
  462
+Gui,4: Add,Text,x10 y110 Center,Texter is a text replacement utility designed to save`nyou countless keystrokes on repetitive text entry by`nreplacing user-defined abbreviations (or hotstrings)`nwith your frequently-used text snippets.`n`nTexter is written by Adam Pash and distributed`nby Lifehacker under the GNU Public License.`nFor details on how to use Texter, check out the
  463
+Gui,4:Font,underline bold
  464
+Gui,4:Add,Text,cBlue gHomepage Center x110 y230,Texter homepage
  465
+Gui,4: Color,F8FAF0
  466
+Gui 2:+Disabled
  467
+Gui,4: Show,auto,About Texter
  468
+Return
  469
+
  470
+DISABLE:
  471
+IniRead,disable,texter.ini,Settings,Disable
  472
+if disable = 0
  473
+{
  474
+	IniWrite,1,texter.ini,Settings,Disable
  475
+	EnableTriggers(false)
  476
+	Menu,Tray,Check,&Disable
  477
+}
  478
+else
  479
+{
  480
+	IniWrite,0,texter.ini,Settings,Disable
  481
+	EnableTriggers(true)
  482
+	Menu,Tray,Uncheck,&Disable
  483
+}
  484
+return
  485
+
  486
+Homepage:
  487
+Run http://lifehacker.com/software//lifehacker-code-texter-windows-238306.php
  488
+return
  489
+
  490
+BasicUse:
  491
+Run http://lifehacker.com/software//lifehacker-code-texter-windows-238306.php#basic
  492
+return
  493
+
  494
+Scripting:
  495
+Run http://lifehacker.com/software//lifehacker-code-texter-windows-238306.php#advanced
  496
+return
  497
+
  498
+4GuiClose:
  499
+4GuiEscape:
  500
+DismissAbout:
  501
+Gui 2:-Disabled
  502
+Gui,4: Destroy
  503
+return
  504
+
  505
+HELP:
  506
+Gui,5: Destroy
  507
+Gui,5: Add,Picture,x200 y5,%TexterPNG%
  508
+Gui,5: font, s36, Courier New
  509
+Gui,5: Add, Text,x20 y40,Texter
  510
+Gui,5: font, s9, Arial 
  511
+Gui,5: Add,Text,x19 y285 w300 center,All of Texter's documentation can be found online at the
  512
+Gui,5:Font,underline bold
  513
+Gui,5:Add,Text,cBlue gHomepage Center x125 y305,Texter homepage
  514
+Gui,5: font, s9 norm, Arial 
  515
+Gui,5: Add,Text,x10 y100 w300,For help by topic, click on one of the following:
  516
+Gui,5:Font,underline bold
  517
+Gui,5:Add,Text,x30 y120 cBlue gBasicUse,Basic Use: 
  518
+Gui,5:Font,norm
  519
+Gui,5:Add,Text,x50 y140 w280, Covers how to create basic text replacement hotstrings.
  520
+Gui,5:Font,underline bold
  521
+Gui,5:Add,Text,x30 y180 cBlue gScripting,Sending advanced keystrokes: 
  522
+Gui,5:Font,norm
  523
+Gui,5:Add,Text,x50 y200 w280, Texter is capable of sending advanced keystrokes, like keyboard combinations.  This section lists all of the special characters used in script creation, and offers a few examples of how you might use scripts.
  524
+Gui,5: Color,F8FAF0
  525
+Gui,5: Show,auto,Texter Help
  526
+Return
  527
+
  528
+5GuiEscape:
  529
+DismissHelp:
  530
+Gui,5: Destroy
  531
+return
  532
+
  533
+GetFileList:
  534
+FileList =
  535
+Loop, %A_ScriptDir%\replacements\*.txt
  536
+{
  537
+	thisFile:=Dehexify(A_LoopFileName)
  538
+	FileList = %FileList%%thisFile%|
  539
+}
  540
+StringReplace, FileList, FileList, .txt,,All
  541
+return
  542
+
  543
+PREFERENCES:
  544
+Gui,3: Destroy
  545
+Gui,3: +owner2
  546
+Gui,3: Add, Tab,x5 y5 w306 h230,General|Print|Stats ;|Import|Export Add these later
  547
+Gui,3: Add,Button,x150 y240 w75 GSETTINGSOK Default,&OK
  548
+IniRead,otfhotkey,texter.ini,Hotkey,OntheFly
  549
+Gui,3: Add,Text,x10 y40,On-the-Fly shortcut:
  550
+Gui,3: Add,Hotkey,xp+10 yp+20 w100 vsotfhotkey, %otfhotkey%
  551
+Gui,3: Add,Text,x150 y40,Hotstring Management shortcut:
  552
+Gui,3: Add,Hotkey,xp+10 yp+20 w100 vsmanagehotkey, %managehotkey%
  553
+;code optimization -- use mode value to set in initial radio values
  554
+CompatMode := NOT MODE
  555
+Gui,3: Add,Radio,x10 y100 vModeGroup Checked%CompatMode%,Compatibility mode (Default)
  556
+Gui,3: Add,Radio,Checked%MODE%,Clipboard mode (Faster, but less compatible)
  557
+OnStartup := GetValFromIni(Settings, Startup, false)
  558
+Gui,3: Add,Checkbox, vStartup x20 yp+30 Checked%OnStartup%,Run Texter at start up
  559
+IniRead,Update,texter.ini,Preferences,UpdateCheck
  560
+Gui,3: Add,Checkbox, vUpdate x20 yp+20 Checked%Update%,Check for updates at launch?
  561
+IniRead,ExSound,texter.ini,Preferences,ExSound
  562
+Gui,3: Add,Checkbox, vExSound x20 yp+20 gToggle Checked%ExSound%,Play sound when replacement triggered?
  563
+IniRead,Synergy,texter.ini,Preferences,Synergy
  564
+Gui,3: Add,Checkbox, vSynergy x20 yp+20 gToggle Checked%Synergy%,Make Texter compatible across computers with Synergy?
  565
+;Gui,3: Add,Button,x150 y200 w75 GSETTINGSOK Default,&OK
  566
+Gui,3: Add,Button,x230 y240 w75 GSETTINGSCANCEL,&Cancel
  567
+Gui,3: Tab,2
  568
+Gui,3: Add,Button,w150 h150 gPrintableList,Create Printable Texter Cheatsheet
  569
+Gui,3: Add,Text,xp+160 y50 w125 Wrap,Click the big button to export a printable cheatsheet of all your Texter hotstrings, replacements, and triggers.
  570
+Gui,3: Tab,3
  571
+Gui,3: Add,Text,x10 y40,Your Texter stats:
  572
+IniRead,expanded,texter.ini,Stats,Expanded
  573
+Gui,3: Add,Text,x25 y60,Snippets expanded:   %expanded% 
  574
+IniRead,chars_saved,texter.ini,Stats,Characters
  575
+Gui,3: Add,Text,x25 y80,Characters saved:     %chars_saved%
  576
+SetFormat,FLOAT,0.2
  577
+time_saved := chars_saved/24000
  578
+Gui,3: Add,Text,x25 y100,Hours saved:             %time_saved% (assuming 400 chars/minute)
  579
+;Gui,3: Add,Button,x150 y200 w75 GSETTINGSOK Default,&OK
  580
+;Gui,3: Add,Button,x230 y200 w75 GSETTINGSCANCEL,&Cancel
  581
+Gui 2:+Disabled
  582
+Gui,3: Show,AutoSize,Texter Preferences
  583
+Return
  584
+
  585
+SETTINGSOK:
  586
+Gui,3: Submit, NoHide
  587
+If (sotfhotkey != otfhotkey)
  588
+{
  589
+	otfhotkey:=sotfhotkey
  590
+	If otfhotkey<>
  591
+	{
  592
+	  Hotkey,IfWinNotActive,Texter Preferences
  593
+	  Hotkey,%otfhotkey%,Newkey
  594
+	  HotKey,%otfhotkey%,On
  595
+	  Hotkey,IfWinActive
  596
+	}
  597
+	IniWrite,%otfhotkey%,texter.ini,Hotkey,OntheFly
  598
+}
  599
+
  600
+If (smanagehotkey != managehotkey)
  601
+{
  602
+	managehotkey:=smanagehotkey
  603
+	If managehotkey<>
  604
+	{
  605
+	  Hotkey,IfWinNotActive,Texter Preferences
  606
+	  Hotkey,%managehotkey%,Manage
  607
+	  HotKey,%managehotkey%,On
  608
+	  Hotkey,IfWinActive
  609
+	}
  610
+	IniWrite,%managehotkey%,texter.ini,Hotkey,Management
  611
+}
  612
+;code optimization -- calculate MODE from ModeGroup
  613
+MODE := ModeGroup - 1
  614
+IniWrite,%MODE%,texter.ini,Settings,Mode
  615
+IniWrite,%Update%,texter.ini,Preferences,UpdateCheck
  616
+If Startup = 1
  617
+{
  618
+	IfNotExist %A_StartMenu%\Programs\Startup\Texter.lnk
  619
+		;Get icon for shortcut link:
  620
+		;1st from compiled EXE
  621
+		if %A_IsCompiled%
  622
+		{
  623
+			IconLocation=%A_ScriptFullPath%
  624
+		}
  625
+		;2nd from icon in resources folder
  626
+		else IfExist %TexterICO%
  627
+		{
  628
+			IconLocation=%TexterICO%
  629
+		}
  630
+		;3rd from the AutoHotkey application itself
  631
+		else
  632
+		{
  633
+			IconLocation=%A_AhkPath%
  634
+		}
  635
+		;use %A_ScriptFullPath% instead of texter.exe
  636
+		;to allow compatibility with source version
  637
+		FileCreateShortcut,%A_ScriptFullPath%,%A_StartMenu%\Programs\Startup\Texter.lnk,%A_ScriptDir%,,Text replacement system tray application,%IconLocation%
  638
+}
  639
+else
  640
+{
  641
+	IfExist %A_StartMenu%\Programs\Startup\Texter.lnk
  642
+	{
  643
+		FileDelete %A_StartMenu%\Programs\Startup\Texter.lnk
  644
+	}
  645
+}
  646
+IniWrite,%Startup%,texter.ini,Settings,Startup
  647
+3GuiClose:
  648
+3GuiEscape:
  649
+SETTINGSCANCEL:
  650
+Gui 2:-Disabled
  651
+Gui,3: Destroy
  652
+
  653
+Return
  654
+
  655
+TOGGLE:
  656
+GuiControlGet,ToggleValue,,%A_GuiControl%
  657
+IniWrite,%ToggleValue%,texter.ini,Preferences,%A_GuiControl%
  658
+return
  659
+
  660
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Implementation and GUI for management ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  661
+MANAGE:
  662
+GoSub,GetFileList
  663
+Bundles =
  664
+Loop,bundles\*,2
  665
+{
  666
+	Bundles = %Bundles%|%A_LoopFileName%
  667
+	thisBundle = %A_LoopFileName%
  668
+;	Loop,bundles\%A_LoopFileName%\replacements\*.txt
  669
+;	{
  670
+;		thisReplacement:=Dehexify(A_LoopFileName)
  671
+;		thisBundle = %thisBundle%%thisReplacement%|
  672
+;	}
  673
+	StringReplace, thisBundle, thisBundle, .txt,,All
  674
+	StringReplace, thisBundle, thisBundle, %A_LoopFileName%,,
  675
+	%A_LoopFileName% = %thisBundle%
  676
+}
  677
+StringReplace, FileList, FileList, .txt,,All
  678
+StringTrimLeft,Bundles,Bundles,1
  679
+Gui,2: Destroy
  680
+Gui,2: Default
  681
+Gui,2: Font, s12, Arial
  682
+Gui,2: Add,Tab,x5 y5 h390 w597 vBundleTabs gListBundle,Default|%Bundles% ;;;;;; START ADDING BUNDLES
  683
+Gui,2: Add, Text, Section,
  684
+Gui,2: Tab ;;; Every control after this point belongs to no individual tab
  685
+Gui,2: Add, Text,ys xs,Hotstring:
  686
+Gui,2: Add, ListBox, xs r15 W100 vChoice gShowString Sort, %FileList%
  687
+Gui,2: Add, Button, w35 xs+10 GAdd,+
  688
+Gui,2: Add, Button, w35 xp+40 GDelete,-
  689
+Gui,2: Add, DropDownList, Section ys vTextOrScript, Text||Script
  690
+Gui,2: Font, s12, Arial
  691
+Gui,2: Add, Edit, r12 W460 xs vFullText
  692
+Gui,2: Add, Text, xs,Trigger:
  693
+Gui,2: Add, Checkbox, vEnterCbox yp xp+65, Enter
  694
+Gui,2: Add, Checkbox, vTabCbox yp xp+65, Tab
  695
+Gui,2: Add, Checkbox, vSpaceCbox yp xp+60, Space
  696
+Gui,2: Font, s8, Arial
  697
+Gui,2: Add,Button, w80 GPButtonSave xs+375 yp, &Save
  698
+IniRead,bundleCheck,texter.ini,Bundles,Default
  699
+Gui,2: Add, Checkbox, Checked%bundleCheck% vbundleCheck gToggleBundle xs+400 yp+50,Enabled
  700
+Gui,2: Add, Button, w80 Default GPButtonOK xs+290 yp+30,&OK
  701
+Gui,2: Add, Button, w80 xp+90 GPButtonCancel, &Cancel
  702
+Menu, ToolsMenu, Add, P&references..., Preferences
  703
+Menu, MgmtMenuBar, Add, &Tools, :ToolsMenu
  704
+Menu, BundlesMenu, Add, &Export, Export
  705
+Menu, BundlesMenu, Add, &Import, Import
  706
+Menu, BundlesMenu, Add, &Add, AddBundle
  707
+Menu, BundlesMenu, Add, &Remove, DeleteBundle
  708
+Menu, MgmtMenuBar, Add, &Bundles, :BundlesMenu
  709
+Menu, HelpMenu, Add, &Basic Use, BasicUse
  710
+Menu, HelpMenu, Add, Ad&vanced Use, Scripting
  711
+Menu, HelpMenu, Add, &Homepage, Homepage
  712
+Menu, HelpMenu, Add, &About..., About
  713
+Menu, MgmtMenuBar, Add, &Help, :HelpMenu
  714
+Gui,2: Menu, MgmtMenuBar
  715
+Gui,2: Show, , Texter Management
  716
+Hotkey,IfWinActive, Texter Management
  717
+Hotkey,!p,Preferences
  718
+Hotkey,delete,Delete
  719
+Hotkey,IfWinActive
  720
+return
  721
+
  722
+ListBundle:
  723
+if A_GuiControl = BundleTabs
  724
+	GuiControlGet,CurrentBundle,2:,BundleTabs
  725
+IniRead,bundleCheck,texter.ini,Bundles,%CurrentBundle%
  726
+GuiControl,2:,Choice,|
  727
+Loop,bundles\*,2
  728
+{
  729
+	Bundles = %Bundles%|%A_LoopFileName%
  730
+	thisBundle = %A_LoopFileName%
  731
+	Loop,bundles\%A_LoopFileName%\replacements\*.txt
  732
+	{
  733
+		thisReplacement:=Dehexify(A_LoopFileName)
  734
+		thisBundle = %thisBundle%%thisReplacement%|
  735
+	}
  736
+;	StringReplace, thisBundle, thisBundle, .txt,,All
  737
+	StringReplace, thisBundle, thisBundle, %A_LoopFileName%,,
  738
+	%A_LoopFileName% = %thisBundle%
  739
+}
  740
+;if A_GuiControl = Tab
  741
+;	GuiControl,,Choice,|
  742
+;else
  743
+;	GuiControl,,Choice,%RString%||
  744
+GuiControl,2:,FullText,
  745
+GuiControl,2:,EnterCbox,0
  746
+GuiControl,2:,TabCbox,0
  747
+GuiControl,2:,SpaceCbox,0
  748
+GuiControl,2:,bundleCheck,%bundleCheck%
  749
+if CurrentBundle = Default
  750
+{
  751
+	Gosub,GetFileList
  752
+	CurrentBundle = %FileList%
  753
+	GuiControl,,Choice,%CurrentBundle%
  754
+}
  755
+else
  756
+{
  757
+	StringTrimLeft,CurrentBundle,%CurrentBundle%,0
  758
+	GuiControl,2:,Choice,%CurrentBundle%
  759
+}
  760
+return
  761
+
  762
+ToggleBundle:
  763
+GuiControlGet,CurrentBundle,,BundleTabs
  764
+GuiControlGet,bundleCheck,,bundleCheck
  765
+IniWrite,%bundleCheck%,texter.ini,Bundles,%CurrentBundle%
  766
+Gosub,BuildActive
  767
+return
  768
+
  769
+BuildActive:
  770
+activeBundles =
  771
+FileDelete,Active\replacements\*
  772
+FileDelete,Active\bank\*
  773
+Loop,bundles\*,2
  774
+{
  775
+	IniRead,activeCheck,texter.ini,Bundles,%A_LoopFileName%
  776
+	if activeCheck = 1
  777
+		activeBundles = %activeBundles%%A_LoopFileName%,
  778
+}
  779
+IniRead,activeCheck,texter.ini,Bundles,Default
  780
+if activeCheck = 1
  781
+	activeBundles = %activeBundles%Default
  782
+Loop,Parse,activeBundles,CSV
  783
+{
  784
+;	MsgBox,%A_LoopField%
  785
+	if A_LoopField = Default
  786
+	{
  787
+		FileCopy,replacements\*.txt,Active\replacements
  788
+		FileRead,tab,bank\tab.csv
  789
+		FileAppend,%tab%,Active\bank\tab.csv
  790
+		FileRead,space,bank\space.csv
  791
+		FileAppend,%space%,Active\bank\space.csv
  792
+		FileRead,enter,bank\enter.csv
  793
+		FileAppend,%enter%,Active\bank\enter.csv
  794
+	}
  795
+	else
  796
+	{
  797
+		FileCopy,Bundles\%A_LoopField%\replacements\*.txt,active\replacements
  798
+		FileRead,tab,Bundles\%A_LoopField%\bank\tab.csv
  799
+		FileAppend,%tab%,active\bank\tab.csv
  800
+		FileRead,space,Bundles\%A_LoopField%\bank\space.csv
  801
+		FileAppend,%space%,active\bank\space.csv
  802
+		FileRead,enter,Bundles\%A_LoopField%\bank\enter.csv
  803
+		FileAppend,%enter%,active\bank\enter.csv
  804
+	}
  805
+;		IfExist active\replacements\wc.txt
  806
+;			MsgBox,%A_LoopFileName% put me here
  807
+}
  808
+FileRead, EnterKeys, %A_WorkingDir%\Active\bank\enter.csv
  809
+FileRead, TabKeys, %A_WorkingDir%\Active\bank\tab.csv
  810
+FileRead, SpaceKeys, %A_WorkingDir%\Active\bank\space.csv
  811
+ActiveList =
  812
+Loop, Active\replacements\*.txt
  813
+{
  814
+	ActiveList = %ActiveList%%A_LoopFileName%|
  815
+}
  816
+StringReplace, ActiveList, ActiveList, .txt,,All
  817
+
  818
+return
  819
+
  820
+ADD:
  821
+EnableTriggers(false)
  822
+GoSub,Newkey
  823
+IfWinExist,Add new hotstring...
  824
+{
  825
+	WinWaitClose,Add new hotstring...,,
  826
+}
  827
+;GoSub,GetFileList
  828
+GoSub,ListBundle
  829
+StringReplace, CurrentBundle, CurrentBundle,|%RString%|,|%RString%||
  830
+GuiControl,,Choice,|%CurrentBundle%
  831
+EnableTriggers(true)
  832
+GoSub,ShowString
  833
+return
  834
+
  835
+DELETE:
  836
+Gui 2:+OwnDialogs
  837
+GuiControlGet,ActiveChoice,,Choice
  838
+GuiControlGet,CurrentBundle,,BundleTabs
  839
+if (CurrentBundle != "") and (CurrentBundle != "Default")
  840
+	RemoveFromDir = Bundles\%CurrentBundle%\
  841
+else
  842
+	RemoveFromDir = 
  843
+
  844
+MsgBox,1,Confirm Delete,Are you sure you want to delete this hotstring: %ActiveChoice%
  845
+IfMsgBox, OK
  846
+{
  847
+	ActiveChoice:=Hexify(ActiveChoice)
  848
+	FileDelete,%A_ScriptDir%\%RemoveFromDir%replacements\%ActiveChoice%.txt
  849
+	DelFromBank(ActiveChoice, RemoveFromDir, "enter")
  850
+	DelFromBank(ActiveChoice, RemoveFromDir, "tab")
  851
+	DelFromBank(ActiveChoice, RemoveFromDir, "space")
  852
+	GoSub,ListBundle
  853
+	Gosub,BuildActive
  854
+	GuiControl,,Choice,|%CurrentBundle%
  855
+	GuiControl,,FullText,
  856
+	GuiControl,,EnterCbox,0
  857
+	GuiControl,,TabCbox,0
  858
+	GuiControl,,SpaceCbox,0
  859
+}
  860
+return
  861
+
  862
+ShowString:
  863
+GuiControlGet,ActiveChoice,,Choice
  864
+ActiveChoice:=Hexify(ActiveChoice)
  865
+GuiControlGet,CurrentBundle,,BundleTabs
  866
+if CurrentBundle = Default
  867
+	ReadFrom = 
  868
+else
  869
+	ReadFrom = bundles\%CurrentBundle%\
  870
+
  871
+FileRead,enter,%ReadFrom%bank\enter.csv
  872
+FileRead,tab,%ReadFrom%bank\tab.csv
  873
+FileRead,space,%ReadFrom%bank\space.csv
  874
+
  875
+if ActiveChoice in %enter%
  876
+{
  877
+	GuiControl,,EnterCbox,1
  878
+}
  879
+else
  880
+	GuiControl,,EnterCbox,0
  881
+if ActiveChoice in %tab%
  882
+{
  883
+	GuiControl,,TabCbox,1
  884
+}
  885
+else
  886
+	GuiControl,,TabCbox,0
  887
+if ActiveChoice in %space%
  888
+{
  889
+	GuiControl,,SpaceCbox,1
  890
+}
  891
+else
  892
+	GuiControl,,SpaceCbox,0
  893
+FileRead, Text, %ReadFrom%replacements\%ActiveChoice%.txt
  894
+IfInString,Text,::scr::
  895
+{
  896
+	GuiControl,,TextOrScript,|Text|Script||
  897
+	StringReplace,Text,Text,::scr::,,
  898
+}
  899
+else
  900
+	GuiControl,,TextOrScript,|Text||Script
  901
+GuiControl,,FullText,%Text%
  902
+return
  903
+
  904
+PButtonSave:
  905
+Gui,2: Submit, NoHide
  906
+IsScript := (TextOrScript == "Script")
  907
+
  908
+If Choice <>
  909
+{
  910
+	if (CurrentBundle != "") and (CurrentBundle != "Default")
  911
+		SaveToDir = Bundles\%CurrentBundle%\
  912
+	else
  913
+		SaveToDir = 
  914
+	PSaveSuccessful := SaveHotstring(Choice, FullText, IsScript, SaveToDir, SpaceCbox, TabCbox, EnterCbox)
  915
+}
  916
+else
  917
+{
  918
+	PSaveSuccessful = true
  919
+}
  920
+return
  921
+
  922
+2GuiEscape:
  923
+PButtonCancel:
  924
+Gui,2: Destroy
  925
+return
  926
+
  927
+PButtonOK:
  928
+Gosub,PButtonSave
  929
+if PSaveSuccessful
  930
+	Gui,2: Submit
  931
+return
  932
+
  933
+AddBundle:
  934
+EnableTriggers(false)
  935
+Hotkey,IfWinActive,New Bundle
  936
+Hotkey,Space,NOSPACE
  937
+Hotkey,IfWinActive
  938
+InputBox,BundleName,New Bundle,What would you like to call your bundle? (no spaces),,160,150,,,
  939
+if ErrorLevel
  940
+{
  941
+	EnableTriggers(true)
  942
+	return
  943
+}
  944
+else
  945
+{
  946
+	IfExist bundles\%BundleName%
  947
+		MsgBox,,Bundle already in use,%BundleName% bundle already exists.`nChoose another name or delete the current %BundleName% bundle.
  948
+	else
  949
+	{
  950
+		FileCreateDir,bundles\%BundleName%
  951
+		FileCreateDir,bundles\%BundleName%\replacements
  952
+		FileCreateDir,bundles\%BundleName%\bank
  953
+		IniWrite,1,texter.ini,Bundles,%BundleName%
  954
+		Bundles =
  955
+		Loop,bundles\*,2
  956
+		{
  957
+			Bundles = %Bundles%|%A_LoopFileName%
  958
+			;thisBundle = %A_LoopFileName%
  959
+			if BundleName = %A_LoopFileName%
  960
+				Bundles = %Bundles%|
  961
+		}
  962
+		GuiControl,,BundleTabs,|Default|%Bundles%
  963
+		GuiControl,,Choice,|
  964
+	}
  965
+}
  966
+EnableTriggers(true)
  967
+return
  968
+
  969
+NOSPACE:
  970
+Msgbox,0,Oops...,Whoops... Bundle names must not have any spaces.
  971
+return
  972
+
  973
+DeleteBundle:
  974
+GuiControlGet,CurrentBundle,,BundleTabs
  975
+if CurrentBundle = Default
  976
+{
  977
+	MsgBox,You can't remove the Default bundle.
  978
+	return
  979
+}
  980
+MsgBox,4,Confirm bundle delete,Are you sure you want to remove the %CurrentBundle% bundle?
  981
+IfMsgBox, Yes
  982
+{
  983
+	FileRemoveDir,bundles\%CurrentBundle%,1
  984
+	Bundles =
  985
+	Loop,bundles\*,2
  986
+	{
  987
+		Bundles = %Bundles%|%A_LoopFileName%
  988
+	}
  989
+	GuiControl,,BundleTabs,|Default|%Bundles%
  990
+	Gosub,GetFileList
  991
+	GuiControl,,Choice,%FileList%
  992
+}
  993
+return
  994
+
  995
+EXPORT:
  996
+GuiControlGet,CurrentBundle,,BundleTabs
  997
+MsgBox,4,Confirm Bundle Export,Are you sure you want to export the %CurrentBundle% bundle?
  998
+IfMsgBox, Yes
  999
+{
  1000
+	IfNotExist %A_WorkingDir%\Texter Export
  1001
+		FileCreateDir,%A_WorkingDir%\Texter Exports
  1002
+	FileDelete,Texter Exports\%CurrentBundle%.texter
  1003
+	IniWrite,%CurrentBundle%,Texter Exports\%CurrentBundle%.texter,Info,Name
  1004
+	if (CurrentBundle = "Default")
  1005
+		BundleDir = 
  1006
+	else
  1007
+		BundleDir = bundles\%CurrentBundle%\
  1008
+	Loop,%BundleDir%replacements\*,0
  1009
+	{
  1010
+		FileRead,replacement,%A_LoopFileFullPath%
  1011
+		IfInString,replacement,`r`n
  1012
+			StringReplace,replacement,replacement,`r`n,`%bundlebreak,All
  1013
+		IniWrite,%A_LoopFileName%,Texter Exports\%CurrentBundle%.texter,%A_Index%,Hotstring
  1014
+		IniWrite,%replacement%,Texter Exports\%CurrentBundle%.texter,%A_Index%,Replacement
  1015
+	}
  1016
+	MsgBox,4,Your bundle was successfully created!,Congratulations, your bundle was successfully exported!`nYou can now share your bundle with the world by sending them the %CurrentBundle%.texter file.`nThey can add it to Texter through the import feature. `n`nWould you like to see the %CurrentBundle% bundle?
  1017
+IfMsgBox, Yes
  1018
+	Run,Texter Exports\
  1019
+}
  1020
+
  1021
+return
  1022
+
  1023
+IMPORT:
  1024
+FileSelectFile, ImportBundle,,, Import Texter bundle, *.texter
  1025
+if ErrorLevel = 0
  1026
+{
  1027
+	IniRead,BundleName,%ImportBundle%,Info,Name
  1028
+	IfExist bundles\%BundleName%
  1029
+	{
  1030
+		MsgBox,4,%BundleName% bundle already installed,%BundleName% bundle already installed.`nWould you like to overwrite previous %BundleName% bundle?
  1031
+		IfMsgBox, No
  1032
+			return
  1033
+		else
  1034
+		{
  1035
+			FileRemoveDir,bundles\%BundleName%,1
  1036
+		}
  1037
+	}
  1038
+	FileCreateDir,bundles\%BundleName%
  1039
+	FileCreateDir,bundles\%BundleName%\replacements
  1040
+	FileCreateDir,bundles\%BundleName%\bank
  1041
+	
  1042
+	Loop
  1043
+	{
  1044
+		IniRead,file,%ImportBundle%,%A_Index%,Hotstring
  1045
+		IniRead,replacement,%ImportBundle%,%A_Index%,Replacement
  1046
+		StringReplace, hotstring, file, .txt
  1047
+		StringReplace,replacement,replacement,`%bundlebreak,`r`n,All
  1048
+		bundleCollection = %hotstring%,%bundleCollection%
  1049
+		if file = ERROR
  1050
+				break
  1051
+		else
  1052
+			FileAppend,%replacement%,bundles\%BundleName%\replacements\%file%
  1053
+	}
  1054
+	Gui, 8: Add, Text, Section x10 y10,What triggers would you like to use with the %BundleName% bundle?
  1055
+	Gui,8: Add, Checkbox, vEnterCbox x30, Enter
  1056
+	Gui,8: Add, Checkbox, vTabCbox yp xp+65, Tab
  1057
+	Gui,8: Add, Checkbox, vSpaceCbox yp xp+60, Space
  1058
+	Gui,8: Add,Button, x180 Default w80 GCreateBank,&OK
  1059
+	Gui, 8: Show,,Set default triggers
  1060
+}
  1061
+return
  1062
+
  1063
+CreateBank:
  1064
+Gui,8: Submit
  1065
+Gui,8: Destroy
  1066
+if EnterCbox = 1
  1067
+	FileAppend,%bundleCollection%,bundles\%BundleName%\bank\enter.csv
  1068
+if TabCbox = 1
  1069
+	FileAppend,%bundleCollection%,bundles\%BundleName%\bank\tab.csv
  1070
+if SpaceCbox = 1
  1071
+	FileAppend,%bundleCollection%,bundles\%BundleName%\bank\space.csv
  1072
+MsgBox,4,Enable %BundleName% bundle?,Would you like to enable the %BundleName% bundle?
  1073
+IfMsgBox,Yes
  1074
+{
  1075
+	IniWrite,1,texter.ini,Bundles,%BundleName%
  1076
+	Gosub,BuildActive
  1077
+}
  1078
+else
  1079
+	IniWrite,0,texter.ini,Bundles,%BundleName%
  1080
+Bundles =
  1081
+Loop,bundles\*,2
  1082
+{
  1083
+	Bundles = %Bundles%%A_LoopFileName%|
  1084
+	;thisBundle = %A_LoopFileName%
  1085
+	if BundleName = %A_LoopFileName%
  1086
+		Bundles = %Bundles%|
  1087
+}
  1088
+GuiControl,2:,BundleTabs,|Default|%Bundles%
  1089
+Gosub,ListBundle
  1090
+return
  1091
+
  1092
+;; method written by Dustin Luck for writing to ini
  1093
+GetValFromIni(section, key, default)
  1094
+{
  1095
+	IniRead,IniVal,texter.ini,%section%,%key%
  1096
+	if IniVal = ERROR
  1097
+	{
  1098
+		IniWrite,%default%,texter.ini,%section%,%key%
  1099
+		IniVal := default
  1100
+	}
  1101
+	return IniVal
  1102
+}
  1103
+
  1104
+SaveHotstring(HotString, Replacement, IsScript, Bundle, SpaceIsTrigger, TabIsTrigger, EnterIsTrigger)
  1105
+{
  1106
+global EnterCSV
  1107
+global TabCSV
  1108
+global SpaceCSV
  1109
+global EnterKeys
  1110
+global TabKeys
  1111
+global SpaceKeys
  1112
+	HotString:=Hexify(HotString)
  1113
+	successful := false
  1114
+	if (!EnterIsTrigger AND !TabIsTrigger AND !SpaceIsTrigger)
  1115
+	{