#include-once
#include <Array.au3>
#include <ButtonConstants.au3>
#include <EditConstants.au3>
#include <GUIConstantsEx.au3>
#include <ListViewConstants.au3>
#include <StaticConstants.au3>
#include <StructureConstants.au3>
#include <WindowsConstants.au3>
#include <File.au3>
#include <GUIListView.au3>
#include <GuiEdit.au3>
Opt("GUIOnEventMode", 1)

Global $ScitePath = RegRead("HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\SciTE.exe", "")
Global $KeyWordPath = StringReplace($ScitePath, "SciTE.exe", "properties\au3.keywords.abbreviations.properties")
Global $MyKeyWordPath = @UserProfileDir & '\au3.keywords.my'
Global $Abbr_Path = @UserProfileDir & '\abbrev.properties'
Global $MyAbbrevPath = @UserProfileDir & '\abbrev.properties.my'
	   If Not FileExists($MyAbbrevPath) Then
		   Local $fh = FileOpen($MyAbbrevPath, 1)
		   FileWriteLine($fh, '; >> My own abbrevs <<')
		   FileClose($fh)
	   EndIf
Global $Start_STR = '#; -- Gui Variables --', $start = False, $edit = False
Global $Last_STR = '#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#'
Global $txt, $aTitel[2] = ['Code für neue Abkürzung', 'Code bearbeiten']
Global $aLabel[2] = [ _
'Bitte den Code für die Abkürzung einfügen. Einrückungen bitte mit Tabulator (Im Editfeld durch STRG+TAB).' & @LF & _
		'Für die gewünschte Cursorposition:  |  verwenden. Der Code wird beim Schließen des Fensters übernommen.', _
'Hier den Code bearbeiten. Einrückungen bitte mit Tabulator (Im Editfeld durch STRG+TAB).' & @LF & _
		'Für die gewünschte Cursorposition:  |  verwenden. Der Code wird beim Schließen des Fensters übernommen.']
Global $aAbbrev
_FileReadToArray($Abbr_Path, $aAbbrev)

$Form1 = GUICreate("Abkürzungen verwalten  [" & $Abbr_Path & ']', 800, 620, -1, -1)
GUISetOnEvent($GUI_EVENT_CLOSE, "Form1Close")
$mnu = GUICtrlCreateMenu('Wiederherstellung')
$mnu_restore = GUICtrlCreateMenuItem('Wiederherstellung eigener Abbrevs', $mnu)
GUICtrlSetOnEvent(-1, '_Restore')
$iSearch = GUICtrlCreateInput('', 15, 10, 90, 20)
$bSearch = GUICtrlCreateButton('Suchen', 125, 10, 150, 20, $BS_DEFPUSHBUTTON)
GUICtrlSetOnEvent(-1, '_Search')
$bCreate = GUICtrlCreateButton('Hinzufügen', 295, 10, 150, 20)
GUICtrlSetOnEvent(-1, '_Create')
$bEdit = GUICtrlCreateButton('Bearbeiten', 465, 10, 150, 20)
GUICtrlSetOnEvent(-1, '_Edit')
$bDelete = GUICtrlCreateButton('Löschen', 635, 10, 150, 20)
GUICtrlSetOnEvent(-1, '_Delete')
$ListView1 = GUICtrlCreateListView("Abkürzung|Code", 15, 40, 770, 545, BitOR($LVS_SHOWSELALWAYS,$LVS_SINGLESEL,$WS_HSCROLL,$WS_VSCROLL))
GUICtrlSetOnEvent(-1, "ListView1Click")
GUICtrlSetBkColor(-1, 0xFF4400)
GUICtrlSetBkColor(-1, $GUI_BKCOLOR_LV_ALTERNATE)
GUICtrlSendMsg(-1, $LVM_SETEXTENDEDLISTVIEWSTYLE, $LVS_EX_ONECLICKACTIVATE, $LVS_EX_ONECLICKACTIVATE)
_GUICtrlListView_SetColumnWidth(-1, 0, 90)
_GUICtrlListView_SetColumnWidth(-1, 1, $LVSCW_AUTOSIZE_USEHEADER)

_LV_Fill()

$Form2 = GUICreate('Code zur Abkürzung', 700, 400, -1, -1)
GUISetOnEvent($GUI_EVENT_CLOSE, "Form2Close")
$Edit1 = GUICtrlCreateEdit('', 10, 10, 680, 380, BitOR($GUI_SS_DEFAULT_EDIT,$ES_READONLY))
GUICtrlSetBkColor(-1, 0x98FB98)

$Form3 = GUICreate('Code für neue Abkürzung', 700, 400, -1, -1)
GUISetOnEvent($GUI_EVENT_CLOSE, "Form3Close")
$Label1 = GUICtrlCreateLabel('Bitte den Code für die Abkürzung einfügen. Einrückungen bitte mit Tabulator (Im Editfeld durch STRG+TAB).' & @LF & _
		'Für die gewünschte Cursorposition:  |  verwenden. Der Code wird beim Schließen des Fensters übernommen.' _
		, 10, 5, 680, 30, $SS_SUNKEN+$SS_CENTER)
GUICtrlSetBkColor(-1, 0x98FB98)
$Edit2 = GUICtrlCreateEdit('', 10, 40, 680, 350, BitOR($WS_HSCROLL,$WS_VSCROLL,$ES_MULTILINE,$ES_WANTRETURN))
GUICtrlSetBkColor(-1, 0x98FB98)

GUISetState(@SW_SHOW, $Form1)
GUIRegisterMsg($WM_NOTIFY, "MY_WM_COMMAND")

While 1
	Sleep(100)
WEnd

Func Form1Close()
	Exit
EndFunc   ;==>Form1Close

Func Form2Close()
	GUISetState(@SW_HIDE, $Form2)
	GUICtrlSetData($Edit1, '')
EndFunc   ;==>Form2Close

Func Form3Close()
	GUISetState(@SW_HIDE, $Form3)
	If $edit Then
		_WriteEditedAbbrev()
	Else
		_WriteNewAbbrev()
	EndIf
EndFunc   ;==>Form3Close

Func _Search()
	$txt = GUICtrlRead($iSearch)
	If $txt = '' Then Return
	Local $indx = _LV_FindInSubItem($ListView1, $txt, 0)
	If $indx = -1 Then
		MsgBox(0, 'Suche Abbrev', 'Abbrev: "' & $txt & '" existiert nicht.')
	Else
		_GUICtrlListView_EnsureVisible($ListView1, $indx)
		_GUICtrlListView_SetItemSelected($ListView1, $indx)
	EndIf
EndFunc   ;==>_Search

Func _Create()
	$txt = GUICtrlRead($iSearch)
	If $txt = '' Then Return MsgBox(16, 'Fehler', 'Keine Abkürzung eingetragen.')
	Local $indx = _LV_FindInSubItem($ListView1, $txt, 0)
	If $indx > -1 Then Return MsgBox(16, 'Fehler', 'Die Abkürzung existiert bereits.')
	$edit = False
	WinSetTitle($Form3, '', $aTitel[0])
	GUICtrlSetData($Label1, $aLabel[0])
	GUISetState(@SW_SHOW, $Form3)
EndFunc

Func _Edit()
	$txt = GUICtrlRead($iSearch)
	If $txt = '' Then Return MsgBox(16, 'Fehler', 'Keine Abkürzung ausgewählt.')
	$edit = True
	WinSetTitle($Form3, '', $aTitel[1])
	GUICtrlSetData($Label1, $aLabel[1])
	GUICtrlSetData($Edit2, _Abbrev2Code(_GUICtrlListView_GetItemText($ListView1, _LV_FindInSubItem($ListView1, $txt, 0), 1)))
	GUISetState(@SW_SHOW, $Form3)
EndFunc   ;==>_Edit

Func _Restore()
	Local $aMyAbbrev, $split_a, $split_f
	_FileReadToArray($MyAbbrevPath, $aMyAbbrev)
	For $i = 2 To UBound($aMyAbbrev) - 1
		$start = False
		For $j = 1 To UBound($aAbbrev) - 1
			If $aAbbrev[$j] = $Start_STR Then $start = True
			If (Not $start) Or (StringLeft($aAbbrev[$j], 1) = '#') Or ($aAbbrev[$j] = '') Then ContinueLoop
			$split_a = _SplitOnce($aAbbrev[$j])
			If @error Then ContinueLoop
			$split_f = _SplitOnce($aMyAbbrev[$i])
			If @error Then ContinueLoop
			If $split_a[0] = $split_f[0] Then
				ConsoleWrite($split_f[0] & @CRLF)
				$aAbbrev[$j] = $split_f[0] & '=' & $split_f[1]
				WinSetTitle($Form1, '', 'Restore Abbrev: ' & $split_f[0])
				$aMyAbbrev[$i] = -1
				ExitLoop
			EndIf
		Next
	Next
	For $i = 2 To UBound($aMyAbbrev) - 1
		If $aMyAbbrev[$i] = -1 Then ContinueLoop
		$split_f = _SplitOnce($aMyAbbrev[$i])
		WinSetTitle($Form1, '', 'Restore Abbrev: ' & $split_f[0])
		Sleep(20)
		ReDim $aAbbrev[UBound($aAbbrev) + 1]
		$aAbbrev[UBound($aAbbrev) - 1] = $aMyAbbrev[$i]
		For $j = UBound($aAbbrev) - 1 To 1 Step -1
			If $aAbbrev[$j] = $Last_STR Then ExitLoop
		Next
		_ArraySwap($aAbbrev[UBound($aAbbrev) - 1], $aAbbrev[$j])
	Next
	FileMove($Abbr_Path, $Abbr_Path & '.BAK', 1)
	_FileWriteFromArray($Abbr_Path, $aAbbrev, 1)
	If FileExists($MyKeyWordPath) Then
		Local $aMyKeyWord
		_FileReadToArray($MyKeyWordPath, $aMyKeyWord)
		For $i = 1 To UBound($aMyKeyWord) - 1
			WinSetTitle($Form1, '', 'Restore Keyword: ' & $aMyKeyWord[$i])
			Sleep(20)
			_KeyWordSet($aMyKeyWord[$i], 1)
		Next
	EndIf
	_FileReadToArray($Abbr_Path, $aAbbrev)
	WinSetTitle($Form1, '', 'Restore')
	MsgBox(64, 'Restore', 'Restore beendet.', 1.5)
	WinSetTitle($Form1, '', "Abkürzungen verwalten  [" & $Abbr_Path & ']')
	_GUICtrlListView_DeleteAllItems(GUICtrlGetHandle($ListView1))
	_LV_Fill()
EndFunc   ;==>_Restore

Func _LV_FindInSubItem($hWnd, $2Find, $SubIndex)
	Local $out = -1
	For $i = 0 To _GUICtrlListView_GetItemCount($hWnd) - 1
		If _GUICtrlListView_GetItemText($hWnd, $i, $SubIndex) = $2Find Then $out = $i
	Next
	Return $out
EndFunc   ;==>_LV_FindInSubItem

Func ListView1Click()
	Local $indx = _GUICtrlListView_GetHotItem($ListView1)
	GUICtrlSetData($iSearch, _GUICtrlListView_GetItemText($ListView1, $indx, 0))
	GUICtrlSetData($Edit1, _Abbrev2Code(_GUICtrlListView_GetItemText($ListView1, $indx, 1)))
	GUISetState(@SW_SHOW, $Form2)
EndFunc   ;==>ListView1Click

Func _LV_Fill()
	GUISetState(@SW_LOCK, $Form1)
	Local $k = 0
	$start = False
	For $i = 1 To UBound($aAbbrev) - 1
		If $aAbbrev[$i] = $Start_STR Then $start = True
		If (Not $start) Or (StringLeft($aAbbrev[$i], 1) = '#') Or ($aAbbrev[$i] = '') Then ContinueLoop
		$var = _SplitOnce($aAbbrev[$i])
		If @error Then ContinueLoop
		GUICtrlCreateListViewItem('|', $ListView1)
		GUICtrlSetBkColor(-1, 0xFFF278)
		_GUICtrlListView_SetItemText($ListView1, $k, $var[0], 0)
		_GUICtrlListView_SetItemText($ListView1, $k, $var[1], 1)
		$k += 1
	Next
	GUISetState(@SW_UNLOCK, $Form1)
EndFunc   ;==>_LV_Fill

Func _SplitOnce($STRING, $DELIM = '=')
	If Not StringInStr($STRING, $DELIM) Then Return SetError(1, 0, 1)
	Local $out[2]
	Local $len = StringLen($STRING)
	Local $pos = StringInStr($STRING, $DELIM, 1, 1)
	$out[0] = StringLeft($STRING, $pos - 1)
	$out[1] = StringRight($STRING, $len - $pos)
	Return $out
EndFunc   ;==>_SplitOnce

Func _Abbrev2Code($ABBREV)
	Local $out = ''
	$var = StringSplit($ABBREV, '\n', 1)
	For $i = 1 To UBound($var) - 1
		If StringInStr($var[$i], '\t', 1) Then $var[$i] = StringReplace($var[$i], '\t', @TAB)
		If $i = UBound($var) - 1 Then
			$out &= $var[$i]
		Else
			$out &= $var[$i] & @CRLF
		EndIf
	Next
	Return $out
EndFunc   ;==>_Abbrev2Code

Func _Code2Abbrev()
	Local $out = '', $count = _GUICtrlEdit_GetLineCount($Edit2), $line
	If @error Then Return SetError(1)
	For $i = 0 To $count - 1
		$line = _GUICtrlEdit_GetLine($Edit2, $i)
		If StringInStr($line, @TAB, 1) Then $line = StringReplace($line, @TAB, '\t')
		If $i = $count - 1 Then
			$out &= $line
		Else
			$out &= $line & '\n'
		EndIf
	Next
	Return $out
EndFunc   ;==>_Code2Abbrev

Func _WriteNewAbbrev()
	If GUICtrlRead($Edit2) = '' Then Return
	Local $abbr = _Code2Abbrev()
	Local $fh = FileOpen($MyAbbrevPath, 1)
	FileWriteLine($fh, $txt & '=' & $abbr)
	FileClose($fh)
	ReDim $aAbbrev[UBound($aAbbrev) + 1]
	$aAbbrev[UBound($aAbbrev) - 1] = $txt & '=' & $abbr
	For $i = UBound($aAbbrev) - 1 To 1 Step -1
		If $aAbbrev[$i] = $Last_STR Then ExitLoop
	Next
	_ArraySwap($aAbbrev[UBound($aAbbrev) - 1], $aAbbrev[$i])
	FileMove($Abbr_Path, $Abbr_Path & '.BAK', 1)
	_FileWriteFromArray($Abbr_Path, $aAbbrev, 1)
	_KeyWordSet($txt)
	$fh = FileOpen($MyKeyWordPath, 1)
	FileWrite($fh, $txt & @CRLF)
	FileClose($fh)
	_FileReadToArray($Abbr_Path, $aAbbrev)
	_GUICtrlListView_DeleteAllItems(GUICtrlGetHandle($ListView1))
	GUICtrlSetData($Edit2, '')
	$start = False
	$k = 0
	_LV_Fill()
	Local $idx = _LV_FindInSubItem($ListView1, $txt, 0)
	_GUICtrlListView_EnsureVisible($ListView1, $idx)
	_GUICtrlListView_SetItemSelected($ListView1, $idx)
	Reload_Config()
EndFunc   ;==>_WriteNewAbbrev

Func _WriteEditedAbbrev()
	If GUICtrlRead($Edit2) = '' Then Return
	Local $abbr = _Code2Abbrev()
	Local $fh = FileOpen($MyAbbrevPath, 0)
	Local $content = FileRead($fh)
	FileClose($fh)
	If Not StringRegExp($content, '\r\n' & $txt & '=') Then
		$fh = FileOpen($MyAbbrevPath, 1)
		FileWriteLine($fh, $txt & '=' & $abbr)
		FileClose($fh)
	Else
		$fh = FileOpen($MyAbbrevPath, 0)
		Local $line, $row = 2
		While 1
			$line = FileReadLine($fh, $row)
			If @error = -1 Then ExitLoop
			$split_f = _SplitOnce($line)
			If $txt = $split_f[0] Then ExitLoop
			$row += 1
		WEnd
		FileClose($fh)
		_FileWriteToLine($MyAbbrevPath, $row, $txt & '=' & $abbr, 1)
	EndIf
	Local $line = _GetLine() - 1
	Local $idx = _LV_FindInSubItem($ListView1, $txt, 0)
	$aAbbrev[$line] = $txt & '=' & $abbr
	_GUICtrlListView_DeleteAllItems(GUICtrlGetHandle($ListView1))
	GUICtrlSetData($Edit2, '')
	$start = False
	$k = 0
	_LV_Fill()
	_FileWriteToLine($Abbr_Path, $line, $txt & '=' & $abbr, 1)
	_GUICtrlListView_EnsureVisible($ListView1, $idx)
	_GUICtrlListView_SetItemSelected($ListView1, $idx)
	Reload_Config()
EndFunc   ;==>_WriteEditedAbbrev

Func _Delete()
	$txt = GUICtrlRead($iSearch)
	If MsgBox(262180, 'Achtung', 'Soll die Abkürzung ' & @LF & '>> ' & $txt & ' <<' & @LF & ' wirklich gelöscht werden?') = 7 Then Return
	Local $idx = _GetLine() - 1
	$aAbbrev[$idx] = ''
	_GUICtrlListView_DeleteAllItems(GUICtrlGetHandle($ListView1))
	GUICtrlSetData($iSearch, '')
	$start = False
	$k = 0
	_LV_Fill()
	_FileWriteToLine($Abbr_Path, $idx, '', 1)
	$fh = FileOpen($MyAbbrevPath, 0)
	Local $line, $row = 2
	While 1
		$line = FileReadLine($fh, $row)
		If @error = -1 Then ExitLoop
		$split_f = _SplitOnce($line)
		If @error Then ContinueLoop
		If $txt = $split_f[0] Then ExitLoop
		$row += 1
	WEnd
	FileClose($fh)
	_FileWriteToLine($MyAbbrevPath, $row, '', 1)
	Local $keys = FileRead($KeyWordPath)
	$keys = StringReplace($keys, $txt & ' ', '', 1, 1)
	Local $fh = FileOpen($KeyWordPath, 2)
	FileWrite($fh, $keys)
	FileClose($fh)
	$keys = FileRead($MyKeyWordPath)
	$keys = StringReplace($keys, $txt & @CRLF, '', 1, 1)
	$fh = FileOpen($MyKeyWordPath, 2)
	FileWrite($fh, $keys)
	FileClose($fh)
	Reload_Config()
EndFunc   ;==>_Delete

Func _GetLine()
	Local $var
	For $i = 1 To UBound($aAbbrev) - 1
		$var = _SplitOnce($aAbbrev[$i], '=')
		If @error Then ContinueLoop
		If $var[0] = $txt Then Return $i + 1
	Next
EndFunc   ;==>_GetLine

Func _KeyWordSet($KEYWORD, $CHECK = 0)
	Local $txtZeile, $len
	If $CHECK Then
		Local $fh = FileOpen($KeyWordPath, 0)
		Local $read = FileRead($fh)
		FileClose($fh)
		If StringInStr($read, $KEYWORD & ' ', 1) Then Return
	EndIf
	$zeile = _FileCountLines($KeyWordPath)
	$txtZeile = FileReadLine($KeyWordPath, $zeile)
	$len = StringLen($txtZeile) + 4
	If $len + StringLen($KEYWORD) > 100 Then
		_FileWriteToLine($KeyWordPath, $zeile, $txtZeile & "\" & @CRLF, 1)
		_FileWriteToLine($KeyWordPath, $zeile + 1, @TAB & $KEYWORD & " ", 1)
	Else
		_FileWriteToLine($KeyWordPath, $zeile, $txtZeile & $KEYWORD & " ", 1)
	EndIf
EndFunc   ;==>_KeyWordSet

Func MY_WM_COMMAND($hWnd, $Msg, $wParam, $lParam)
	Switch $wParam
		Case $ListView1
			Local $tagNMHDR = DllStructCreate("int;int;int", $lParam)
			If @error Then Return $GUI_RUNDEFMSG
			If DllStructGetData($tagNMHDR, 3) = $NM_CLICK Then ListView1Click()
	EndSwitch
	Return $GUI_RUNDEFMSG
EndFunc   ;==>MY_WM_COMMAND

; Thanks to Jos for following functions:
Func Reload_Config()
    ;Send SciTE Director my GUI handle so it will report info back from SciTE
    SendSciTE_Command("reloadproperties:")
EndFunc   ;==>Reload_Config
; Send command to SciTE
Func SendSciTE_Command($sCmd, $Wait_For_Return_Info = 0)
    Local $WM_COPYDATA = 74
    Local $WM_GETTEXT = 0x000D
    Local $WM_GETTEXTLENGTH = 0x000E224
    Local Const $SCI_GETLINE = 2153
    Local $Scite_hwnd = WinGetHandle("DirectorExtension") ; Get SciTE DIrector Handle
    Local $My_Hwnd = GUICreate("AutoIt3-SciTE interface") ; Create GUI to receive SciTE info
    Local $My_Dec_Hwnd = Dec(StringTrimLeft($My_Hwnd, 2)) ; Convert my Gui Handle to decimal
    $sCmd = ":" & $My_Dec_Hwnd & ":" & $sCmd ; Add dec my gui handle to commandline to tell SciTE where to send the return info
    ConsoleWrite('SciTE Command  --> ' & $sCmd & @LF)
    Local $CmdStruct = DllStructCreate('Char[' & StringLen($sCmd) + 1 & ']')
    DllStructSetData($CmdStruct, 1, $sCmd)
    Local $COPYDATA = DllStructCreate('Ptr;DWord;Ptr')
    DllStructSetData($COPYDATA, 1, 1)
    DllStructSetData($COPYDATA, 2, StringLen($sCmd) + 1)
    DllStructSetData($COPYDATA, 3, DllStructGetPtr($CmdStruct))
    DllCall('User32.dll', 'None', 'SendMessage', 'HWnd', $Scite_hwnd, _
            'Int', $WM_COPYDATA, 'HWnd', $My_Hwnd, _
            'Ptr', DllStructGetPtr($COPYDATA))
    GUIDelete($My_Hwnd)
EndFunc   ;==>SendSciTE_Command
