AutoHotkey.ahk, from darwin11

AutoHotkey.ahk, from darwin11

; Tips {{{
; #: win
; !: alt
; ^: ctrl
; +: shift
; &: and
; <: only left, >: only right
; *: wildecard
; ~: pass through
; }}}

; Auto-execute section {{{
; Auto execute section is the region before any return/hotkey

; Windows size
TMargin=5
BMargin=5
LMargin=5
RMargin=155 ; sidebar = 150px
MinSize=0.7

; For Terminal/Vim
GroupAdd Terminal, ahk_class PuTTY
GroupAdd Terminal, ahk_class mintty ; cygwin
GroupAdd TerminalVim, ahk_group Terminal
GroupAdd TerminalVim, ahk_class Vim

#Include  %A_ScriptDir%\vim.ahk

Return
; }}}

; Basic Settings, HotKeys, Functions {{{
; Settings

#UseHook On ; Make it a bit slow, but can avoid infinitude loop
            ; Same as "$" for each hotkey
#InstallKeybdHook ; For checking key history
                  ; Use ~500kB memory?

#HotkeyInterval 2000 ; Hotkey inteval (default 2000 milliseconds).
#MaxHotkeysPerInterval 70 ; Max hotkeys perinterval (default 50).

; For HHK
;vkFFsc079::RAlt
;vkFFsc07b::LAlt
vkFFsc079::RCtrl
vkFFsc07b::LCtrl

;; Ref for IME: http://www6.atwiki.jp/eamat/pages/17.html
;; Get IME Status. 0: Off, 1: On
;IME_GET(WinTitle="A")  {
;  ControlGet,hwnd,HWND,,,%WinTitle%
;  if (WinActive(WinTitle)) {
;    ptrSize := !A_PtrSize ? 4 : A_PtrSize
;    VarSetCapacity(stGTI, cbSize:=4+4+(PtrSize*6)+16, 0)
;    NumPut(cbSize, stGTI,  0, "UInt")   ;   DWORD   cbSize;
;    hwnd := DllCall("GetGUIThreadInfo", Uint,0, Uint,&stGTI)
;        ? NumGet(stGTI,8+PtrSize,"UInt") : hwnd
;  }
;
;  Return DllCall("SendMessage"
;      , UInt, DllCall("imm32\ImmGetDefaultIMEWnd", Uint,hwnd)
;      , UInt, 0x0283  ;Message : WM_IME_CONTROL
;      ,  Int, 0x0005  ;wParam  : IMC_GETOPENSTATUS
;      ,  Int, 0)      ;lParam  : 0
;}
;; Get input status. 1: Converting, 2: Have converting window, 0: Others
;IME_GetConverting(WinTitle="A",ConvCls="",CandCls="") {
;  ; Input windows, candidate windows (Add new IME with "|")
;  ConvCls .= (ConvCls ? "|" : "")                 ;--- Input Window ---
;    .  "ATOK\d+CompStr"                           ; ATOK
;    .  "|imejpstcnv\d+"                           ; MS-IME
;    .  "|WXGIMEConv"                              ; WXG
;    .  "|SKKIME\d+\.*\d+UCompStr"                 ; SKKIME Unicode
;    .  "|MSCTFIME Composition"                    ; Google IME
;  CandCls .= (CandCls ? "|" : "")                 ;--- Candidate Window ---
;    .  "ATOK\d+Cand"                              ; ATOK
;    .  "|imejpstCandList\d+|imejpstcand\d+"       ; MS-IME 2002(8.1)XP
;    .  "|mscandui\d+\.candidate"                  ; MS Office IME-2007
;    .  "|WXGIMECand"                              ; WXG
;    .  "|SKKIME\d+\.*\d+UCand"                    ; SKKIME Unicode
; CandGCls := "GoogleJapaneseInputCandidateWindow" ; Google IME
;
;  ControlGet,hwnd,HWND,,,%WinTitle%
;  if (WinActive(WinTitle)) {
;    ptrSize := !A_PtrSize ? 4 : A_PtrSize
;    VarSetCapacity(stGTI, cbSize:=4+4+(PtrSize*6)+16, 0)
;    NumPut(cbSize, stGTI,  0, "UInt")   ;   DWORD   cbSize;
;    hwnd := DllCall("GetGUIThreadInfo", Uint,0, Uint,&stGTI)
;      ? NumGet(stGTI,8+PtrSize,"UInt") : hwnd
;  }
;
;  WinGet, pid, PID,% "ahk_id " hwnd
;  tmm:=A_TitleMatchMode
;  SetTitleMatchMode, RegEx
;  ret := WinExist("ahk_class " . CandCls . " ahk_pid " pid) ? 2
;      :  WinExist("ahk_class " . CandGCls                 ) ? 2
;      :  WinExist("ahk_class " . ConvCls . " ahk_pid " pid) ? 1
;      :  0
;  SetTitleMatchMode, %tmm%
;  Return ret
;}
;; Set IME, SetSts=0: Off, 1: On, return 0 for success, others for non-success
;IME_SET(SetSts=0, WinTitle="A")    {
;  ControlGet,hwnd,HWND,,,%WinTitle%
;  if(WinActive(WinTitle)){
;    ptrSize := !A_PtrSize ? 4 : A_PtrSize
;    VarSetCapacity(stGTI, cbSize:=4+4+(PtrSize*6)+16, 0)
;    NumPut(cbSize, stGTI,  0, "UInt")   ;   DWORD   cbSize;
;    hwnd := DllCall("GetGUIThreadInfo", Uint,0, Uint,&stGTI)
;        ? NumGet(stGTI,8+PtrSize,"UInt") : hwnd
;  }
;
;  Return DllCall("SendMessage"
;    , UInt, DllCall("imm32\ImmGetDefaultIMEWnd", Uint,hwnd)
;    , UInt, 0x0283  ;Message : WM_IME_CONTROL
;    ,  Int, 0x006   ;wParam  : IMC_SETOPENSTATUS
;    ,  Int, SetSts) ;lParam  : 0 or 1
;}

; }}}

; Terminal/Vim {{{
; ESC + IME
#IfWInActive, ahk_group TerminalVim
Esc:: ; Just send Esc at converting.
  if (VIM_IME_GET(A)) {
    if (VIM_IME_GetConverting(A)) {
      Send,{Esc}
    } else {
      VIM_IME_SET()
    }
  } else {
    Send,{Esc}
  }
  Return
^[:: ; Go to Normal mode (for vim) with IME off even at converting.
  if (VIM_IME_GET(A)) {
    Send,{Esc}
    Sleep 1 ; wait 1 ms (Need to stop converting)
    VIM_IME_SET()
    Send,{Esc}
  } else {
    Send,{Esc}
  }
  Return
#IfWInActive

; Paste
#IfWInActive, ahk_group Terminal
!v::
  StringSplit, strout, clipboard, `n
  If(strout0>1 or InStr(clipboard, "sudo")>0) {
    MsgBox, 308, Clipboard, %clipboard%`n`n Do you want to paste?
    IfMsgBox, No
    {
      Return
    }
  }
  Sleep,200
  MouseClick, Right, 50, 50, 1
  Return
#IfWInActive
#IfWInActive, ahk_class Vim
!v::Send,{Alt}ep
#IfWInActive

; Other than Terminal/Vim
#IfWInNotActive, ahk_group TerminalVim
^[::Send,{Esc}             ; Always C-[ to ESC, like vim
^d::Send,{Del}             ; Always Delete with C-d
#IfWInNotActive
; }}} Terminal/Vim

; Power Point {{{
#IfWInActive, ahk_class PP12FrameClass
; Select one character
^Space::Send,{Right}+{Left}

; Subscript/Superscript
^=::Send,^tb{Enter}
^+=::Send,^tp{Enter}
; For JP keyboards
;^-::Send,^tb{Enter}
;^+-::Send,^tp{Enter}

; Fonts
^+s::Send,^tfsymbol{Enter}
^+a::Send,^tfarial{Enter}
^+h::Send,^tfhelvetica{Enter}
#IfWInActive
; }}} Power Point

; Word {{{
#IfWInActive, ahk_class OpusApp
^Space::Send,{Right}+{Left}
^=::Send,^tb{Enter}
^+=::Send,^tp{Enter}
; for JP keyboards
;^-::Send,^tb{Enter}
;^+-::Send,^tp{Enter}
#IfWInActive
; }}} Word

; Explorer {{{
#IfWInActive, ahk_class CabinetWClass
; Next/Previous page
^i::Send,!{Right}
^o::Send,!{Left}
#IfWInActive
; }}} Explorer

; CLCL {{{
;#IfWInActive, ahk_class CLCLMain
#IfWInActive, CLCL ; both window/title do not working...
j::
  Msgbox, clcl_down
  Send,{Down}
  Return
K::Send,{Up}
#IfWInActive
; }}} Explorer

; Everthing {{{
#IfWInActive, ahk_class EVERYTHING
Return::
  Send,{Enter}
  Sleep,200
  IfWinActive, ahk_class EVERYTHING
  {
    Send,{Enter}
    Sleep,500
  }
  WinActivate, ahk_class EVERYTHING
  Sleep,200
  Send,{Esc}
  Return
#IfWInActive
; }}} Everything

; Command Prompt {{{
#IfWinActive ahk_class ConsoleWindowClass
^v::
  SendInput %clipboard%
  Return
#IfWInActive
; }}} Command Prompt

; Global Settings {{{
#if
; Basic Settings {{{

; Suspend
;Esc & Tab::
;  Suspend, Toggle
;  Return
; For Alt-Ctrl Swap (swapped by KeySwap)
LCtrl & Tab::AltTab
Alt & Tab::
  if GetKeyState("Shift","P") {
    Send,^+{taB} ; dosen't work ()
  }else{
    Send,^{Tab}
  }
  Return
;!m::Send,^m
;^m::Send,!m
^m::Send,!m
Ctrl & Left::Send,!{Left}
Ctrl & Right::Send,!{Right}

; Other basic settings
!Space::Send,{vkF3sc029}   ; IME by A-Space
^Space::Send,{vkF3sc029}   ; IME by C-Space
; {vkF3sc029}              ; 変換
; {vk1Dsc07B}              ; 無変換
!a::Send,^{Space}n        ; Minimize window
!4::Send,!{F4}             ; Close window
^4::Send,!{F4}             ; Close window
!d::Send,{Del}             ; Always Delete with A-d
;^o::Send,!{Left}           ; Go to previous page
;^i::Send,!{Right}          ; Go to nexe page
^Space::!`                 ; IME

;^h::Send,{BS}              ; Always BS with C-h
^h::
  n=0
  TrayTip,Start:,%n%,10,,
  While GetKeyState("h","p"){
    Send {BS}
    n:= n+1
    TrayTip,Start:,%n%,10,,
    Sleep 100
  }
  return

; For HHK
; ESC to ` like normal keyboard (ESC is placed on the left of 1 in HHK)
!1::!`                ; IME
; }}} Basic Settings

; Cursor, Mouse, Window move/size {{{
; Cursor {{{
!^h::Send,{Left}
!^j::Send,{Down}
!^k::Send,{Up}
!^l::Send,{Right}
; }}} Cursor

; Mouse {{{
; Mouse Move
!^y::MouseMove, -10, 0, 0, R
!^u::MouseMove, 0, 10, 0, R
!^i::MouseMove, 0, -10, 0, R
!^o::MouseMove, 10, 0, 0, R

; Click
!^n::MouseClick, Left
!^p::MouseClick, Right
; Right click on current window

; Mouse wheel
!^m::MouseClick, WheelDown,,,  2
!^,::MouseClick, WheelUp,,,  2
; }}} Mouse

; Window move {{{
^+y::
  WinGetPos, X, Y, , , A ;A for Active Window
  ;Msgbox, Pos At %X% %Y%
  WinMove, A, ,X-20, Y,
  ;Msgbox, Moved At %X%-20 %Y%
  Return ; Necessary for mapping which has at least 2 commands
^+u::
  WinGetPos, X, Y, , , A
  WinMove, A, ,X, Y+20
  Return
^+i::
  WinGetPos, X, Y, , , A
  WinMove, A, ,X, Y-20
  Return
^+o::
  WinGetPos, X, Y, , , A
  WinMove, A, ,X+20, Y
  Return
; }}} Window move

; Window size {{{
^!Enter::
  ;WinGetPos, X, Y, W, H, Program Manager ; Full Desktop
  ;Msgbox, Pos At %X% %Y% %W% %H%
  SysGet, MWA, MonitorWorkArea ; w/o Taskbar
  ;Msgbox, %MWALeft% %MWATop% %MWARight% %MWABottom%
  WinMove, A, ,MWALeft+LMargin, MWATop+TMargin
    , MWARight-MWALeft-LMargin-RMargin
    , MWABottom-MWATop-TMargin-BMargin
  Return
^!+Enter::
  ;WinGetPos, X, Y, W, H, Program Manager ; Full Desktop
  ;Msgbox, Pos At %X% %Y% %W% %H%
  SysGet, MWA, MonitorWorkArea ; w/o Taskbar
  ;Msgbox, %MWALeft% %MWATop% %MWARight% %MWABottom%
  WinMove, A, ,MWALeft+LMargin, MWATop+TMargin
    , (MWARight-MWALeft-LMargin-RMargin)*minsize
    , (MWABottom-MWATop-TMargin-BMargin)*minsize
  Return
; }}} Window size
; }}} Cursor, Mouse, Window move
; }}} Global Settings

; Tips {{{
; #: win
; !: alt
; ^: ctrl
; +: shift
; &: and
; <: only left, >: only right
; *: wildecard
; ~: pass through
; }}}

; Auto-execute section {{{
; Auto execute section is the region before any return/hotkey

; Windows size
TMargin=5
BMargin=5
LMargin=5
RMargin=155 ; sidebar = 150px
MinSize=0.7

; For Terminal/Vim
GroupAdd Terminal, ahk_class PuTTY
GroupAdd Terminal, ahk_class mintty ; cygwin
GroupAdd TerminalVim, ahk_group Terminal
GroupAdd TerminalVim, ahk_class Vim

#Include  %A_ScriptDir%\vim.ahk

Return
; }}}

; Basic Settings, HotKeys, Functions {{{
; Settings

#UseHook On ; Make it a bit slow, but can avoid infinitude loop
            ; Same as "$" for each hotkey
#InstallKeybdHook ; For checking key history
                  ; Use ~500kB memory?

#HotkeyInterval 2000 ; Hotkey inteval (default 2000 milliseconds).
#MaxHotkeysPerInterval 70 ; Max hotkeys perinterval (default 50).

; For HHK
;vkFFsc079::RAlt
;vkFFsc07b::LAlt
vkFFsc079::RCtrl
vkFFsc07b::LCtrl

;; Ref for IME: http://www6.atwiki.jp/eamat/pages/17.html
;; Get IME Status. 0: Off, 1: On
;IME_GET(WinTitle="A")  {
;  ControlGet,hwnd,HWND,,,%WinTitle%
;  if (WinActive(WinTitle)) {
;    ptrSize := !A_PtrSize ? 4 : A_PtrSize
;    VarSetCapacity(stGTI, cbSize:=4+4+(PtrSize*6)+16, 0)
;    NumPut(cbSize, stGTI,  0, "UInt")   ;   DWORD   cbSize;
;    hwnd := DllCall("GetGUIThreadInfo", Uint,0, Uint,&stGTI)
;        ? NumGet(stGTI,8+PtrSize,"UInt") : hwnd
;  }
;
;  Return DllCall("SendMessage"
;      , UInt, DllCall("imm32\ImmGetDefaultIMEWnd", Uint,hwnd)
;      , UInt, 0x0283  ;Message : WM_IME_CONTROL
;      ,  Int, 0x0005  ;wParam  : IMC_GETOPENSTATUS
;      ,  Int, 0)      ;lParam  : 0
;}
;; Get input status. 1: Converting, 2: Have converting window, 0: Others
;IME_GetConverting(WinTitle="A",ConvCls="",CandCls="") {
;  ; Input windows, candidate windows (Add new IME with "|")
;  ConvCls .= (ConvCls ? "|" : "")                 ;--- Input Window ---
;    .  "ATOK\d+CompStr"                           ; ATOK
;    .  "|imejpstcnv\d+"                           ; MS-IME
;    .  "|WXGIMEConv"                              ; WXG
;    .  "|SKKIME\d+\.*\d+UCompStr"                 ; SKKIME Unicode
;    .  "|MSCTFIME Composition"                    ; Google IME
;  CandCls .= (CandCls ? "|" : "")                 ;--- Candidate Window ---
;    .  "ATOK\d+Cand"                              ; ATOK
;    .  "|imejpstCandList\d+|imejpstcand\d+"       ; MS-IME 2002(8.1)XP
;    .  "|mscandui\d+\.candidate"                  ; MS Office IME-2007
;    .  "|WXGIMECand"                              ; WXG
;    .  "|SKKIME\d+\.*\d+UCand"                    ; SKKIME Unicode
; CandGCls := "GoogleJapaneseInputCandidateWindow" ; Google IME
;
;  ControlGet,hwnd,HWND,,,%WinTitle%
;  if (WinActive(WinTitle)) {
;    ptrSize := !A_PtrSize ? 4 : A_PtrSize
;    VarSetCapacity(stGTI, cbSize:=4+4+(PtrSize*6)+16, 0)
;    NumPut(cbSize, stGTI,  0, "UInt")   ;   DWORD   cbSize;
;    hwnd := DllCall("GetGUIThreadInfo", Uint,0, Uint,&stGTI)
;      ? NumGet(stGTI,8+PtrSize,"UInt") : hwnd
;  }
;
;  WinGet, pid, PID,% "ahk_id " hwnd
;  tmm:=A_TitleMatchMode
;  SetTitleMatchMode, RegEx
;  ret := WinExist("ahk_class " . CandCls . " ahk_pid " pid) ? 2
;      :  WinExist("ahk_class " . CandGCls                 ) ? 2
;      :  WinExist("ahk_class " . ConvCls . " ahk_pid " pid) ? 1
;      :  0
;  SetTitleMatchMode, %tmm%
;  Return ret
;}
;; Set IME, SetSts=0: Off, 1: On, return 0 for success, others for non-success
;IME_SET(SetSts=0, WinTitle="A")    {
;  ControlGet,hwnd,HWND,,,%WinTitle%
;  if(WinActive(WinTitle)){
;    ptrSize := !A_PtrSize ? 4 : A_PtrSize
;    VarSetCapacity(stGTI, cbSize:=4+4+(PtrSize*6)+16, 0)
;    NumPut(cbSize, stGTI,  0, "UInt")   ;   DWORD   cbSize;
;    hwnd := DllCall("GetGUIThreadInfo", Uint,0, Uint,&stGTI)
;        ? NumGet(stGTI,8+PtrSize,"UInt") : hwnd
;  }
;
;  Return DllCall("SendMessage"
;    , UInt, DllCall("imm32\ImmGetDefaultIMEWnd", Uint,hwnd)
;    , UInt, 0x0283  ;Message : WM_IME_CONTROL
;    ,  Int, 0x006   ;wParam  : IMC_SETOPENSTATUS
;    ,  Int, SetSts) ;lParam  : 0 or 1
;}

; }}}

; Terminal/Vim {{{
; ESC + IME
#IfWInActive, ahk_group TerminalVim
Esc:: ; Just send Esc at converting.
  if (VIM_IME_GET(A)) {
    if (VIM_IME_GetConverting(A)) {
      Send,{Esc}
    } else {
      VIM_IME_SET()
    }
  } else {
    Send,{Esc}
  }
  Return
^[:: ; Go to Normal mode (for vim) with IME off even at converting.
  if (VIM_IME_GET(A)) {
    Send,{Esc}
    Sleep 1 ; wait 1 ms (Need to stop converting)
    VIM_IME_SET()
    Send,{Esc}
  } else {
    Send,{Esc}
  }
  Return
#IfWInActive

; Paste
#IfWInActive, ahk_group Terminal
!v::
  StringSplit, strout, clipboard, `n
  If(strout0>1 or InStr(clipboard, "sudo")>0) {
    MsgBox, 308, Clipboard, %clipboard%`n`n Do you want to paste?
    IfMsgBox, No
    {
      Return
    }
  }
  Sleep,200
  MouseClick, Right, 50, 50, 1
  Return
#IfWInActive
#IfWInActive, ahk_class Vim
!v::Send,{Alt}ep
#IfWInActive

; Other than Terminal/Vim
#IfWInNotActive, ahk_group TerminalVim
^[::Send,{Esc}             ; Always C-[ to ESC, like vim
^d::Send,{Del}             ; Always Delete with C-d
#IfWInNotActive
; }}} Terminal/Vim

; Power Point {{{
#IfWInActive, ahk_class PP12FrameClass
; Select one character
^Space::Send,{Right}+{Left}

; Subscript/Superscript
^=::Send,^tb{Enter}
^+=::Send,^tp{Enter}
; For JP keyboards
;^-::Send,^tb{Enter}
;^+-::Send,^tp{Enter}

; Fonts
^+s::Send,^tfsymbol{Enter}
^+a::Send,^tfarial{Enter}
^+h::Send,^tfhelvetica{Enter}
#IfWInActive
; }}} Power Point

; Word {{{
#IfWInActive, ahk_class OpusApp
^Space::Send,{Right}+{Left}
^=::Send,^tb{Enter}
^+=::Send,^tp{Enter}
; for JP keyboards
;^-::Send,^tb{Enter}
;^+-::Send,^tp{Enter}
#IfWInActive
; }}} Word

; Explorer {{{
#IfWInActive, ahk_class CabinetWClass
; Next/Previous page
^i::Send,!{Right}
^o::Send,!{Left}
#IfWInActive
; }}} Explorer

; CLCL {{{
;#IfWInActive, ahk_class CLCLMain
#IfWInActive, CLCL ; both window/title do not working...
j::
  Msgbox, clcl_down
  Send,{Down}
  Return
K::Send,{Up}
#IfWInActive
; }}} Explorer

; Everthing {{{
#IfWInActive, ahk_class EVERYTHING
Return::
  Send,{Enter}
  Sleep,200
  IfWinActive, ahk_class EVERYTHING
  {
    Send,{Enter}
    Sleep,500
  }
  WinActivate, ahk_class EVERYTHING
  Sleep,200
  Send,{Esc}
  Return
#IfWInActive
; }}} Everything

; Command Prompt {{{
#IfWinActive ahk_class ConsoleWindowClass
^v::
  SendInput %clipboard%
  Return
#IfWInActive
; }}} Command Prompt

; Global Settings {{{
#if
; Basic Settings {{{

; Suspend
;Esc & Tab::
;  Suspend, Toggle
;  Return
; For Alt-Ctrl Swap (swapped by KeySwap)
LCtrl & Tab::AltTab
Alt & Tab::
  if GetKeyState("Shift","P") {
    Send,^+{taB} ; dosen't work ()
  }else{
    Send,^{Tab}
  }
  Return
;!m::Send,^m
;^m::Send,!m
^m::Send,!m
Ctrl & Left::Send,!{Left}
Ctrl & Right::Send,!{Right}

; Other basic settings
!Space::Send,{vkF3sc029}   ; IME by A-Space
^Space::Send,{vkF3sc029}   ; IME by C-Space
; {vkF3sc029}              ; 変換
; {vk1Dsc07B}              ; 無変換
^h::Send,{BS}              ; Always BS with C-h
!a::Send,^{Space}n        ; Minimize window
!4::Send,!{F4}             ; Close window
^4::Send,!{F4}             ; Close window
!d::Send,{Del}             ; Always Delete with A-d
;^o::Send,!{Left}           ; Go to previous page
;^i::Send,!{Right}          ; Go to nexe page
^Space::!`                 ; IME

; For HHK
; ESC to ` like normal keyboard (ESC is placed on the left of 1 in HHK)
!1::!`                ; IME
; }}} Basic Settings

; Cursor, Mouse, Window move/size {{{
; Cursor {{{
!^h::Send,{Left}
!^j::Send,{Down}
!^k::Send,{Up}
!^l::Send,{Right}
; }}} Cursor

; Mouse {{{
; Mouse Move
!^y::MouseMove, -10, 0, 0, R
!^u::MouseMove, 0, 10, 0, R
!^i::MouseMove, 0, -10, 0, R
!^o::MouseMove, 10, 0, 0, R

; Click
!^n::MouseClick, Left
!^p::MouseClick, Right
; Right click on current window

; Mouse wheel
!^m::MouseClick, WheelDown,,,  2
!^,::MouseClick, WheelUp,,,  2
; }}} Mouse

; Window move {{{
^+y::
  WinGetPos, X, Y, , , A ;A for Active Window
  ;Msgbox, Pos At %X% %Y%
  WinMove, A, ,X-20, Y,
  ;Msgbox, Moved At %X%-20 %Y%
  Return ; Necessary for mapping which has at least 2 commands
^+u::
  WinGetPos, X, Y, , , A
  WinMove, A, ,X, Y+20
  Return
^+i::
  WinGetPos, X, Y, , , A
  WinMove, A, ,X, Y-20
  Return
^+o::
  WinGetPos, X, Y, , , A
  WinMove, A, ,X+20, Y
  Return
; }}} Window move

; Window size {{{
^!Enter::
  ;WinGetPos, X, Y, W, H, Program Manager ; Full Desktop
  ;Msgbox, Pos At %X% %Y% %W% %H%
  SysGet, MWA, MonitorWorkArea ; w/o Taskbar
  ;Msgbox, %MWALeft% %MWATop% %MWARight% %MWABottom%
  WinMove, A, ,MWALeft+LMargin, MWATop+TMargin
    , MWARight-MWALeft-LMargin-RMargin
    , MWABottom-MWATop-TMargin-BMargin
  Return
^!+Enter::
  ;WinGetPos, X, Y, W, H, Program Manager ; Full Desktop
  ;Msgbox, Pos At %X% %Y% %W% %H%
  SysGet, MWA, MonitorWorkArea ; w/o Taskbar
  ;Msgbox, %MWALeft% %MWATop% %MWARight% %MWABottom%
  WinMove, A, ,MWALeft+LMargin, MWATop+TMargin
    , (MWARight-MWALeft-LMargin-RMargin)*minsize
    , (MWABottom-MWATop-TMargin-BMargin)*minsize
  Return
; }}} Window size
; }}} Cursor, Mouse, Window move
; }}} Global Settings


Fixed Errors

Fixed Errors

/**
 * Track your windows activities.
 *
 * Intended for personal use only.
 *
 * @dufferzafar
 */

/**
 * Script Settings
 *
 * Do not touch if you are unsure of anything.
 */
#NoEnv
#SingleInstance Force
#Persistent
#NoTrayIcon
#KeyHistory 0
SetWorkingDir %A_ScriptDir%

Version := "v0.1"

/**
 * Global Variables
 *
 * Edit only if you are sure enough.
 */

; ######################## Default Setup ########################

; OnExit, Exit

; Create a group of explorer windows
GroupAdd, Explorer, ahk_class CabinetWClass
GroupAdd, Explorer, ahk_class Progman

; Modify the Menu
Menu, Tray, NoStandard
Menu, Tray, Tip, Time Tracker ; %Version%

Menu, Tray, Add, &Suspend, SuspendMe
Menu, Tray, Add, &Exit, CloseMe

; Set the icon if it exist
IfExist, %A_ScriptDir%\Data\Time.ico
   Menu, Tray, Icon, %A_ScriptDir%\Data\Time.ico

Menu, Tray, Icon  ;Else show default icon

; Let the user know we have started
TrayTip, Time Tracker %Version%,
(

Your time is being monitored.
)
SetTimer, RemoveTrayTip, 2500

; ######################## Real Code Begins ########################

wProcess := Object()
activeTime := Object()

; Monitor Active Window every 3 seconds
SetTimer, WindowTally, % 3 * 1000

; Output Data every 15 minutes
SetTimer, FlushToFile, % 15 * 60 * 1000

Return

WindowTally:
   ; WinGet, PName, ProcessName, A
   WinGet, PPath, ProcessPath, A

   ; FileGetVersionInfo_AW(PPAth).ProductName

   title := PPath

   If (activeTime[title] == "")
   {
      wProcess.Insert(title)
      activeTime[title] := 0
   }

   activeTime[title] += 3
Return

#o::
FlushToFile:
   FileDelete, OutputData.txt
   Loop, % wProcess.MaxIndex()
      FileAppend, % wProcess[A_Index] " `t`t "activeTime[wProcess[A_Index]] "`n", OutputData.txt
Return

RemoveTrayTip:
   SetTimer, RemoveTrayTip, Off
   TrayTip
Return

SuspendMe:
   Suspend, Toggle
Return

CloseMe:
   ExitApp

#Include Data\Includes\FileGetVersionInfo.ahk

/**
 * Track your windows activities.
 *
 * Intended for personal use only.
 *
 * @dufferzafar
 */

/**
 * Script Settings
 *
 * Do not touch if you are unsure of anything.
 */
#NoEnv
#SingleInstance Force
#Persistent
#NoTrayIcon
#KeyHistory 0
SetWorkingDir %A_ScriptDir%

Version := "v0.1"

/**
 * Global Variables
 *
 * Edit only if you are sure enough.
 */

; ######################## Default Setup ########################

; OnExit, Exit

; Create a group of explorer windows
GroupAdd, Explorer, ahk_class CabinetWClass
GroupAdd, Explorer, ahk_class Progman

; Modify the Menu
Menu, Tray, NoStandard
Menu, Tray, Tip, Time Tracker ; %Version%

; Set the icon if it exist
IfExist, %A_ScriptDir%\Data\Time.ico
   Menu, Tray, Icon, %A_ScriptDir%\Data\Time.ico

Menu, Tray, Icon  ;Else show default icon

; Let the user know we have started
TrayTip, Time Tracker %Version%,
(

Your time is being monitored.
)
SetTimer, RemoveTrayTip, 2500

; ######################## Real Code Begins ########################

wProcess := Object()
activeTime := Object()

; Monitor Active Window every 3 seconds
SetTimer, WindowTally, % 3 * 1000

; Output Data every 15 minutes
SetTimer, WindowTally, % 15 * 60 * 1000

Return

WindowTally:
   ; WinGet, PName, ProcessName, A
   WinGet, PPath, ProcessPath, A

   ; FileGetVersionInfo_AW(PPAth).ProductName

   title := PPath

   If (activeTime[title] == "")
   {
      wProcess.Insert(title)
      activeTime[title] := 0
   }

   activeTime[title] += 3
Return

FlushToFile:
   FileDelete, OutputData.txt
   Loop, % wProcess.MaxIndex()
      FileAppend, % wProcess[A_Index] " `t`t "activeTime[wProcess[A_Index]] "`n", OutputData.txt
Return

RemoveTrayTip:
   SetTimer, RemoveTrayTip, Off
   TrayTip
Return

#Include Data\Includes\FileGetVersionInfo.ahk


Updated 1 pkg(s) on 2015-08-31: cdex

Updated 1 pkg(s) on 2015-08-31: cdex

https://chocolatey.org/packages/cdex

#NoEnv
SendMode Input
SetWorkingDir %A_ScriptDir%
SetTitleMatchMode, 1   ;begins
DetectHiddenText, off
DetectHiddenWindows, off

WinWait, CDex Setup ahk_class #32770, Thank You for using CDex, 120
WinActivate
ControlClick, Button1, ahk_class #32770

WinWait, Donations | CDex, , 10
WinActivate
Send ^w

ExitApp

#NoEnv
SendMode Input
SetWorkingDir %A_ScriptDir%
SetTitleMatchMode, 1   ;matches if title begins with string
DetectHiddenText, off  ;will not search hidden window text
DetectHiddenWindows, off  ;will not detect hidden windows
WinWait, CDex Setup ahk_class #32770, Thank You for using CDex, 120
WinActivate
ControlClick, Button1, ahk_class #32770
WinWait, Donations ahk_class IEFrame, Navigation Bar, 60
WinActivate
Send ^w
ExitApp


FIX: loop wasn't necessary

FIX: loop wasn't necessary

; default environment
DetectHiddenWindows, off
SetControlDelay, 20

; modified environment
#NoEnv
#NoTrayIcon
DetectHiddenText, off
SetTitleMatchMode, 2

; variables
winTitleIE = - Internet Explorer ahk_class IEFrame ahk_exe iexplore.exe
winTitleAddons = Manage Add-ons ahk_class #32770 ahk_exe iexplore.exe
winTitleEnable = Enable add-on ahk_class #32770 ahk_exe iexplore.exe

Process, Exist, iexplore.exe
if !ErrorLevel = 0 {
  procExists = 1
  WinActivate,%winTitleIE%
} else {
  procExists = 0
  Run, iexplore, , , pid
;  WinWait, ahk_pid %pid%, Address Bar, 60  ;too quick
;  WinActivate, ahk_pid %pid%, , 10
  WinWait, %winTitleIE%, , 60
  WinActivate, %winTitleIE%, , 60
  Send {ALT Down}x{ALT Up}m
  Sleep 250
}

Send {TAB 2}QTTabBar{ALT Down}e{ALT Up}
Sleep 1000

IfWinActive, %winTitleEnable%
{
  Send {ENTER}
  Send {ALT Down}l{ALT Up}
  CloseIE()
  sleep 10000
  Return
}
IfWinActive, %winTitleAddons%
{
  Send {ALT Down}l{ALT Up}
  CloseIE()
}

CloseIE()
{
  if procExists = 1
  {
    WinActivate,%winTitleIE%,
    Send, ^w
  }
  else
  {
    WinClose, ahk_exe iexplore.exe
  }
}

; File Explorer
Run, explorer
WinWait, ahk_exe explorer.exe, , 60
WinActivate, ahk_exe explorer.exe
Sleep 500
SetKeyDelay 50
Send {ALT}
Send {V}
Send {Y}
Send {DOWN 2}
Send {SPACE}
Send {ALT down}{F4}

; default environment
DetectHiddenWindows, off
SetControlDelay, 20

; modified environment
#NoEnv
#NoTrayIcon
DetectHiddenText, off
SetTitleMatchMode, 2

; variables
winTitleIE = - Internet Explorer ahk_class IEFrame ahk_exe iexplore.exe
winTitleAddons = Manage Add-ons ahk_class #32770 ahk_exe iexplore.exe
winTitleEnable = Enable add-on ahk_class #32770 ahk_exe iexplore.exe

Process, Exist, iexplore.exe
if !ErrorLevel = 0 {
  procExists = 1
  WinActivate,%winTitleIE%
} else {
  procExists = 0
  Run, iexplore, , , pid
;  WinWait, ahk_pid %pid%, Address Bar, 60  ;too quick
;  WinActivate, ahk_pid %pid%, , 10
  WinWait, %winTitleIE%, , 60
  WinActivate, %winTitleIE%, , 60
  Sleep 1000
}

Loop {
  Send {ALT Down}x{ALT Up}m
  IfWinExist, %winTitleAddons%
  {
    WinActivate
    break
  }
  Sleep 150
}

Send {TAB 2}QTTabBar{ALT Down}e{ALT Up}
Sleep 1000

IfWinActive, %winTitleEnable%
{
  Send {ENTER}
  Send {ALT Down}l{ALT Up}
  CloseIE()
  sleep 10000
  Return
}
IfWinActive, %winTitleAddons%
{
  Send {ALT Down}l{ALT Up}
  CloseIE()
}

CloseIE()
{
  if procExists = 1
  {
    WinActivate,%winTitleIE%,
    Send, ^w
  }
  else
  {
    WinClose, ahk_exe iexplore.exe
  }
}

; File Explorer
Run, explorer
WinWait, ahk_exe explorer.exe, , 60
WinActivate, ahk_exe explorer.exe
Sleep 500
SetKeyDelay 50
Send {ALT}
Send {V}
Send {Y}
Send {DOWN 2}
Send {SPACE}
Send {ALT down}{F4}


Delete MousePos.ahk

Delete MousePos.ahk

; Shows Mouse-Coordinates upon pressing Alt+x

!x::
MouseGetPos, xpos, ypos
Msgbox, The cursor is at X%xpos% Y%ypos%.
return


Get key layout selection menus working

Get key layout selection menus working

; JKLmouse for AutoHotkey by Michael Geary
; http://www.jklmouse.com/ - documentation
; http://unlicense.org/ - public domain statement

#SingleInstance force

SetRegView, 64

version := "0.2x"

; Use either the embedded icon in a compiled .exe,
; or a separate .ico file when running the .ahk script.
iconPath := RegExReplace( A_ScriptFullPath, "i).ahk$", ".ico" )

regKeySettings := "Software\JKLmouse"

; TODO: protect against invalid registry string
keysLeft := RegStringRead( "KeysLeft", "ESDF" )
keysRight := RegStringRead( "KeysRight", "IJKL" )

keyMap := ""

keyMaps :=
(join
{
	Arrows: "Up~Up Down~Down Left~Left Right~Right",
	NumPad: "7~UpLeft 8~Up 9~UpRight 4~Left 5~Down 6~Right 1~DownLeft 2~Down 3~DownRight",
	IJKL: "U~UpLeft I~Up O~UpRight J~Left K~Down L~Right M~DownLeft ,~Down .~DownRight",
	HJKL: "H~Left J~Down K~Up L~Right",
	ESDF: "W~UpLeft E~Up R~UpRight S~Left D~Down F~Right X~DownLeft C~Down V~DownRight",
	WASD: "Q~UpLeft W~Up E~UpRight A~Left S~Down D~Right Z~DownLeft X~Down C~DownRight"
}
)

; Set up the tray icon and menu
Menu, Tray, Icon, %iconPath%
Menu, Tray, Tip, JKLmouse
Menu, Tray, Add
Menu, Tray, Add, Left Hand: ESDF, MenuESDF
Menu, Tray, Add, Left Hand: WASD, MenuWASD
Menu, Tray, Add
Menu, Tray, Add, Right Hand: IJKL, MenuIJKL
Menu, Tray, Add, Right Hand: HJKL, MenuHJKL
Menu, Tray, Add
Menu, Tray, Add, About JKLmouse, MenuAbout
Menu, Tray, Add, JKLmouse Website, MenuWebsite

Menu, Tray, Check, Left Hand: %keysLeft%
Menu, Tray, Check, Right Hand: %keysRight%

; Display tray balloon
; TODO: more useful content?
; TODO: display this only during an install
TrayTip JKLmouse, The Automatic Keyboard Mouse

; Remove forced delay between triggered mouse events.
; TODO: experiment with this when accelerated
SetMouseDelay, -1

; Hotkey repeat count for acceleration
repeat := 0

SetAllKeyMaps()

;MsgBox % keyMap

SetAllKeys( true )

return

; Read a string value from our settings registry key, or return otherwise if not present
RegStringRead( name, otherwise ) {
	global regKeySettings
	value := ""
	RegRead, value, HKEY_CURRENT_USER, %regKeySettings%, %name%
	if( ErrorLevel )
		return %otherwise%
	return %value%
}

; Write a string value to our settings registry key
RegStringWrite( name, value ) {
	global regKeySettings
	RegWrite, REG_SZ, HKEY_CURRENT_USER, %regKeySettings%, %name%, %value%
}

; TODO: refactor SetKeysLeft() and SetKeysRight()!

SetKeysLeft( keys ) {
	global keysLeft
	if( keys = keysLeft )
		return
	Menu, Tray, Uncheck, Left Hand: %keysLeft%
	keysLeft := keys
	Menu, Tray, Check, Left Hand: %keysLeft%
	RegStringWrite( "KeysLeft", keysLeft )
	ReloadAllKeys()
}

SetKeysRight( keys ) {
	global keysRight
	if( keys = keysRight )
		return
	Menu, Tray, Uncheck, Right Hand: %keysRight%
	keysRight := keys
	Menu, Tray, Check, Right Hand: %keysRight%
	RegStringWrite( "KeysRight", keysRight )
	ReloadAllKeys()
}

; Load the entire set of key maps for all arrow pads and all modifiers
SetAllKeyMaps() {
	global keyMap, keysLeft, keysRight
	keyMap := ""
	SetKeyMap( "Arrows", "NumPad", keysLeft, keysRight )
}

; Load the specified key maps for all modifiers
SetKeyMap( keys* ) {
	global keyMap, keyMaps
    for index, value in keys
        keyMap .= keyMaps[value] . " "
    return SubStr( str, 1, -StrLen(sep) )
}

; Turn off existing key maps, reparse and reload new key maps
ReloadAllKeys() {
	SetAllKeys( false )
	SetAllKeyMaps()
	SetAllKeys( true )
}

; Set up or remove all hotkeys for all modifier keys
SetAllKeys( on ) {
	; Each of these modifier keys enables the same set of JKLmouse hotkeys
	SetKeys( on, "CapsLock" )
	SetKeys( on, "~LButton" )
	SetKeys( on, "~RButton" )
	SetKeys( on, "~MButton" )
	SetKeys( on, "~XButton1" )
	SetKeys( on, "~XButton2" )
}

; Set up or remove all the hotkeys for a specific modifier key
SetKeys( on, mod ) {
	global keyMap
	Loop, Parse, keyMap, %A_Space%
	{
		StringSplit map, A_LoopField, ~
		SetKey( on, mod, map1, "Mouse" . map2 )
	}
}

; Set up or remove one hotkey by combining the modifier and key names.
; Take the specified action on key down,
; and always stop acceleration on key up.
SetKey( on, mod, key, action ) {
	keydown = %mod% & %key%
	if( on ) {
		Hotkey, %keydown%, %action%, On
		Hotkey, %keydown% UP, StopAcceleration, On
	}
	else {
		Hotkey, %keydown%, %action%, Off
		Hotkey, %keydown% UP, StopAcceleration, Off
	}
}

; Move the mouse the specifed x and y distances, both scaled by the
; mouse acceleration factor calculated from the key repeat count.
Move( x, y ) {
	global repeat
	++repeat
	factor := Floor( ( repeat + 1 ) / 2 )
	x := x * factor
	y := y * factor
	MouseMove, x, y, 0, R
}

;ArrayJoin( sep, ary ) {
;    for index, value in ary
;		MsgBox % index
;        ;str .= value . sep
;	MsgBox % str
;    return SubStr( str, 1, -StrLen(sep) )
;}

; Handle the keydown for each of the mouse movement directions
; TODO: Maybe a way to simplify this?
MouseUp:
	Move( 0, -1 )
	return
MouseDown:
	Move( 0, 1 )
	return
MouseLeft:
	Move( -1, 0 )
	return
MouseRight:
	Move( 1, 0 )
	return
MouseUpLeft:
	Move( -1, -1 )
	return
MouseUpRight:
	Move( 1, -1 )
	return
MouseDownLeft:
	Move( -1, 1 )
	return
MouseDownRight:
	Move( 1, 1 )
	return

; Handle the keyup for all hotkeys
StopAcceleration:
	repeat = 0
	return

; Handle the About menu item
MenuAbout:
	MsgBox, 0x2040, JKLmouse by Geary Labs, JKLmouse version %version%`nAutoHotkey version %A_AhkVersion%
	return

; Handle the Website menu item
MenuWebsite:
	Run, http://www.jklmouse.com/
	return

MenuESDF:
	setKeysLeft( "ESDF" )
	return

MenuWASD:
	setKeysLeft( "WASD" )
	return

MenuIJKL:
	setKeysRight( "IJKL" )
	return

MenuHJKL:
	setKeysRight( "HJKL" )
	return

; JKLmouse for AutoHotkey by Michael Geary
; http://www.jklmouse.com/ - documentation
; http://unlicense.org/ - public domain statement

#SingleInstance force

version := "0.2x"

; Use either the embedded icon in a compiled .exe,
; or a separate .ico file when running the .ahk script.
iconPath := RegExReplace( A_ScriptFullPath, "i).ahk$", ".ico" )

keyMap := ""

keyMaps :=
(join
{
	Arrows: "Up~Up Down~Down Left~Left Right~Right",
	NumPad: "7~UpLeft 8~Up 9~UpRight 4~Left 5~Down 6~Right 1~DownLeft 2~Down 3~DownRight",
	IJKL: "U~UpLeft I~Up O~UpRight J~Left K~Down L~Right M~DownLeft ,~Down .~DownRight",
	HJKL: "H~Left J~Down K~Up L~Right",
	ESDF: "W~UpLeft E~Up R~UpRight S~Left D~Down F~Right X~DownLeft C~Down V~DownRight",
	WASD: "Q~UpLeft W~Up E~UpRight A~Left S~Down D~Right Z~DownLeft X~Down C~DownRight"
}
)

; Set up the tray icon and menu
Menu, Tray, Icon, %iconPath%
Menu, Tray, Tip, JKLmouse
Menu, Tray, Add
Menu, Tray, Add, Left Hand: ESDF, MenuESDF
Menu, Tray, Add, Left Hand: WASD, MenuWASD
Menu, Tray, Add
Menu, Tray, Add, Right Hand: IJKL, MenuIJKL
Menu, Tray, Add, Right Hand: HJKL, MenuHJKL
Menu, Tray, Add
Menu, Tray, Add, About JKLmouse, MenuAbout
Menu, Tray, Add, JKLmouse Website, MenuWebsite

Menu, Tray, Check, Left Hand: ESDF
Menu, Tray, Check, Right Hand: IJKL

; Display tray balloon
; TODO: more useful content?
; TODO: display this only during an install
TrayTip JKLmouse, The Automatic Keyboard Mouse

; Remove forced delay between triggered mouse events.
; TODO: experiment with this when accelerated
SetMouseDelay, -1

; Hotkey repeat count for acceleration
repeat := 0

SetKeyMap( "Arrows", "NumPad", "IJKL", "ESDF" )
;SetKeyMap( "Arrows", "NumPad", "HJKL", "WASD" )

;MsgBox % keyMap

SetAllKeys( true )

return

SetKeyMap( keys* ) {
	global keyMap, keyMaps
    for index, value in keys
        keyMap .= keyMaps[value] . " "
    return SubStr( str, 1, -StrLen(sep) )
}

SetAllKeys( on ) {
	; Each of these modifier keys enables the same set of JKLmouse hotkeys
	SetKeys( on, "CapsLock" )
	SetKeys( on, "~LButton" )
	SetKeys( on, "~RButton" )
	SetKeys( on, "~MButton" )
	SetKeys( on, "~XButton1" )
	SetKeys( on, "~XButton2" )
}

; Set up or remove all the hotkeys for a specific modifier key
SetKeys( on, mod ) {
	global keyMap
	Loop, Parse, keyMap, %A_Space%
	{
		StringSplit map, A_LoopField, ~
		SetKey( on, mod, map1, "Mouse" . map2 )
	}
}

; Set up or remove one hotkey by combining the modifier and key names.
; Take the specified action on key down,
; and always stop acceleration on key up.
SetKey( on, mod, key, action ) {
	keydown = %mod% & %key%
	if( on ) {
		Hotkey %keydown%, %action%
		Hotkey %keydown% UP, StopAcceleration
	}
	else {
		Hotkey %keydown%, Off
		Hotkey %keydown% UP, Off
	}
}

; Move the mouse the specifed x and y distances, both scaled by the
; mouse acceleration factor calculated from the key repeat count.
Move( x, y ) {
	global repeat
	++repeat
	factor := Floor( ( repeat + 1 ) / 2 )
	x := x * factor
	y := y * factor
	MouseMove, x, y, 0, R
}

;ArrayJoin( sep, ary ) {
;    for index, value in ary
;		MsgBox % index
;        ;str .= value . sep
;	MsgBox % str
;    return SubStr( str, 1, -StrLen(sep) )
;}

; Handle the keydown for each of the mouse movement directions
; TODO: Maybe a way to simplify this?
MouseUp:
	Move( 0, -1 )
	return
MouseDown:
	Move( 0, 1 )
	return
MouseLeft:
	Move( -1, 0 )
	return
MouseRight:
	Move( 1, 0 )
	return
MouseUpLeft:
	Move( -1, -1 )
	return
MouseUpRight:
	Move( 1, -1 )
	return
MouseDownLeft:
	Move( -1, 1 )
	return
MouseDownRight:
	Move( 1, 1 )
	return

; Handle the keyup for all hotkeys
StopAcceleration:
	repeat = 0
	return

; Handle the About menu item
MenuAbout:
	MsgBox, 0x2040, JKLmouse by Geary Labs, JKLmouse version %version%`nAutoHotkey version %A_AhkVersion%
	return

; Handle the Website menu item
MenuWebsite:
	Run, http://www.jklmouse.com/
	return

MenuESDF:
	return

MenuWASD:
	return

MenuIJKL:
	return

MenuHJKL:
	return


Add OSD for volume switcher

Add OSD for volume switcher


Remove unused shortcut

Remove unused shortcut


Update Parent2Gem.ahk

Update Parent2Gem.ahk

; AutoHotkey Version: 1.1x
; Language:       English
; Author:         8thSeaOfRhye
;
;                     #####         Parent2Gem.ahk - Version 2       #####
;
;                     ##### Description of Purpose and Functionality #####
;
; ###            General             ###
; This script translates a String containing the Parenthesis-( i.e. Bracket-)Version of
; a speccing or combining scheme for gemcraft into actual commands for the gems creation.
; Works best in a STANDALONE FLASHPLAYER set to FULLSCREEN.
; It is hopefully easy to use and customize.
; The section which has to be changed is almost right at the top of the following code,
; namely under the command "!C::", and is commented to indicate the exact usage.
;
; The STANDARD HOTKEY is  Alt + c (No shift!!). This corresponds to "!C".
; Check ahkscript.org for Hotkey usage.
;
; CombiningMode is turned on by default. Speccing still works. Suggestion: Don't turn it off...
;
;
; ###  Syntax for the Bracket-Formula ###
;
; Obviously:
; 		r = Red / b = Black / o = orange / y = yellow
;
; Maybe a little less obviously:
;
;		g / k = copy of gem in the BOTTOM-LEFT! corner of the 12*3 craftingfield
;
; Furthermore:   ### New Features ###
;
;		the numerals 2 to 9 followed by any of the above = Corresponding color (or duplicate, respectively), upgraded 1 to 8 times
;
;		Examples: 9o / 2g = Orange upgraded 8 times (grade 9) / Base-gem (BottomLeft corner) upgraded once
;		(Needless to say, the upgrading happens via the "u"-button.)
;
; And:
;
;		a / s / d  =  use (left / middle / right) gem in the top row of the 3*12 craftingfield
;
;		(The order is inspired by the position of the keys on a standard keyboard.
;		 Attention: Those three can't be used in combination with numerals.)

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.
InitialMode := False ; Initialisation
;CoordMode, Mouse, Screen
CurrentCustom := "(g+g)+(g+g)"
LastDDL := 5
;             I
; #####      V V       																					 #########
; #####       V        INSERT THE SCHEME TO BE COMBINED INBETWEEN THE QUTATION-MARKS IN THE LINE BELOW   #########
ParentStr := "(g+g)+(g+g)"

; #####   						The default example is some random 1024 combine							 #########

!V::
	OptionsMenu()
return

OptionsMenu() {
	Global ParentStr
	Global ChosenCombine
	Global ParentNewStr
	Global ChosenIniMode
	Global IsIniChecked
	Global InitialMode
	Global CustomFormula
	Global PGScript
	Global CustomTemp
	Global LastDDL
	Global CurrentCustom
	Global LastDDLTemp
	Global TempReadOnly

	Gui, New,, Options
	GuiHWND := WinExist()

; ################# DDL ######################
	TempReadOnly := ""
	If LastDDL != 5
		TempReadOnly := "readonly"
	Gui, Add, Text,, Choose your desired combine
	Gui, Add, DropDownList, w200 Choose%LastDDL% vChosenCombine gShowCustomField, killgem_amps64-5-gem|killgem_amps64-5-amps|managem_amps256-30_ieee-gem|managem_amps256-30_ieee-amps|Custom
	Gui, Add, Text,, Custom Bracket Formula:        Attention! Syntaxerrors may lead to chaos!
	Gui, Add, Edit, w400 r3 vCustomFormula %TempReadOnly%, %CurrentCustom%

; ################# INITMODE ################

	Gui, Add, Text,, `n`n In order to reset the coordinates check the following option`: `n
	If (InitialMode = False)
		IsIniChecked := ""
	If (InitialMode = True)
		IsIniChecked := "Checked"
	Gui, Add, Checkbox, vChosenIniMode %IsIniChecked%, Initialisation-Mode
	Gui, Add, Text,, If checked, you will be asked for coordinates the next time the CombiningHotkey is pressed.`n CombiningHotkey is Alt C by default.

;###############Wait For Input ##############

	Gui, Add, Button, default, Ok
	Gui, Show
	WinWaitClose, ahk_id %GuiHWND%
	return

;############### SUBS / Labels #############

	ShowCustomField:
		GuiControlGet, StatusOfDll, , ChosenCombine
		if (StatusOfDll = "custom")
			GuiControl, -readonly, CustomFormula
		else
			GuiControl, +readonly, CustomFormula
	return

	ButtonOk:
		Gui, Submit
		if (ChosenCombine = "killgem_amps64-5-gem") {
			ParentNewStr := "((((b+((b+y)+(y+y)))+((b+(b+y))+(b+(b+(b+b)))))+(((b+b)+(b+(y+y)))+(((b+y)+(y+y))+((y+y)+(y+(y+(y+(y+y))))))))+((((b+(b+y))+(b+(y+y)))+((b+(b+y))+(b+(b+(b+(b+b))))))+(((b+(b+y))+(b+(b+(b+b))))+((b+(b+(b+b)))+((b+(b+b))+((b+(b+b))+(b+(b+(b+(b+b))))))))))"
			LastDDL := 1
		}
		if (ChosenCombine = "killgem_amps64-5-amps") {
			ParentNewStr := "((y+y)+(y+(y+y)))"
			LastDDL := 2
		}

		if (ChosenCombine = "managem_amps256-30_ieee-gem") {
			ParentNewStr := "(((((((b+o)+(b+b))+(b+((o+o)+(b+o))))+(((b+o)+(b+b))+((b+b)+(b+(b+(b+(b+b)))))))+((((b+o)+(b+b))+(b+((o+o)+(o+(o+o)))))+((b+((o+o)+(b+o)))+(((o+o)+(b+o))+((o+o)+(o+(o+(o+(o+(o+(o+o)))))))))))+(((((b+o)+(b+b))+(b+((o+o)+(o+(o+o)))))+(((b+o)+(b+b))+((b+b)+(b+(b+(b+(b+b)))))))+((((b+o)+(b+b))+((b+b)+(b+(b+(b+(b+b))))))+(((b+b)+(b+(b+(b+(b+b)))))+((b+(b+(b+(b+b))))+((b+(b+(b+b)))+((b+(b+b))+((b+b)+(b+(b+(b+(b+(b+b)))))))))))))+((((((b+o)+(b+b))+(b+((b+o)+(o+(o+o)))))+(((b+o)+(b+b))+((b+b)+(b+(b+(b+(b+b)))))))+((((b+o)+(b+b))+(b+((b+o)+(o+(o+o)))))+((b+((o+o)+(b+o)))+(((o+o)+(b+o))+((o+(o+o))+(o+(o+(o+(o+(o+(o+o)))))))))))+(((((b+o)+(b+b))+(b+((b+o)+(o+(o+o)))))+((b+((o+o)+(b+o)))+(((b+o)+(o+(o+o)))+((o+(o+o))+(o+(o+(o+(o+(o+(o+o))))))))))+(((b+((o+o)+(b+o)))+((b+(o+o))+((o+o)+(o+(o+(o+(o+(o+o))))))))+((((o+o)+(b+o))+((o+(o+o))+(o+(o+(o+(o+(o+(o+o))))))))+(((o+o)+(o+(o+(o+(o+(o+o))))))+(((o+o)+(o+(o+(o+(o+(o+o))))))+((o+(o+(o+(o+o))))+((o+(o+(o+o)))+((o+(o+o))+((o+(o+o))+(o+(o+(o+(o+(o+(o+(o+o))))))))))))))))))"
			LastDDL := 3
		}

		if (ChosenCombine = "managem_amps256-30_ieee-amps") {
			ParentNewStr := "((((o+o)+(o+o))+((o+o)+(o+(o+(o+o)))))+(((o+o)+(o+(o+(o+o))))+((o+(o+o))+((o+(o+o))+(o+(o+(o+(o+(o+(o+(o+o)))))))))))"
			LastDDL := 4
		}

		if (ChosenCombine = "Custom") {
			ParentNewStr := CustomFormula
			LastDDL := 5
		}

;		if (ChosenCombine = "") {
;			ParentNewStr := ""
;			LastDDL := 1
;		}

		if (ChosenCombine = "")
			ParentNewStr := ParentStr

		FileRead, PGScript, Parent2Gem.ahk
		FileDelete, Parent2Gem.ahk
		ParentNewStr = ParentStr := "%ParentNewStr%"
		PGScript := RegExReplace(PGScript, "ParentStr := ""[A-Za-z0-9()+]*""", ParentNewStr, , 1)

		CustomTemp = CurrentCustom := "%CustomFormula%"
		if (ChosenCombine = "Custom")
			PGScript := RegExReplace(PGScript, "CurrentCustom := "".*""", CustomTemp, , 1)

		LastDDLTemp = LastDDL := %LastDDL%
		PGScript := RegExReplace(PGScript, "LastDDL := [0-9]*", LastDDLTemp, , 1)

		if ((ChosenIniMode = 0) and (InitialMode = True))
			PGScript := RegExReplace(PGScript, "InitialMode := True  `; Init", "InitialMode := False `; Init", , 1)
		if ((ChosenIniMode = 1) and (InitialMode = False))
			PGScript := RegExReplace(PGScript, "InitialMode := False `; Init", "InitialMode := True  `; Init", , 1)

		FileAppend, %PGScript%, Parent2Gem.ahk
		Gui, Destroy
	Reload
}
!C::

CombineMode := True
LastGemPos := 1

TopLeftCornerX := 1590 				;  ####### ENTER THE COORDINATES OF THE 3*12 CRAFTINGFIELD ON YOUR SCREEN #########
TopLeftCornerY := 338				;	###### If you don't know how to obtain those values, you'd better  ########
BottomRightCornerX := 1436			;    ##### ask somebody. They don't have to be really precise.     #######
BottomRightCornerY := 686			;	  #### AND THAT'S IT! The script should work for you now!  ######

if (InitialMode = True) {
	FileRead, PGScript, Parent2Gem.ahk
	FileDelete, Parent2Gem.ahk
	MsgBox Place your mouse over the top-left corner of the 12*3 craftingfield and press ENTER
		MouseGetPos, TLCX, TLCY
		PGScript := RegExReplace(PGScript, "TopLeftCornerX := [0-9]+", "TopLeftCornerX := " TLCX, , 1)
		PGScript := RegExReplace(PGScript, "TopLeftCornerY := [0-9]+", "TopLeftCornerY := " TLCY, , 1)
	MsgBox Place your mouse over the bottom-right corner of the 12*3 craftingfield and press ENTER
		MouseGetPos, BRCX, BRCY
		PGScript := RegExReplace(PGScript, "BottomRightCornerX := [0-9]+", "BottomRightCornerX := "BRCX, , 1)
		PGScript := RegExReplace(PGScript, "BottomRightCornerY := [0-9]+", "BottomRightCornerY := "BRCY, , 1)
		PGScript := RegExReplace(PGScript, "InitialMode := True  `; Init", "InitialMode := False `; Init", , 1)
	FileAppend, %PGScript%, Parent2Gem.ahk

	MsgBox The Script has been initialised and will be reloaded!

	Reload
}
FieldWidth := (BottomRightCornerX - TopLeftCornerX) / 3
FieldHeight := (BottomRightCornerY - TopLeftCornerY) / 12
CraftingField := [BottomRightCornerX -(FieldWidth / 2), BottomRightCornerY -(FieldHeight / 2)]

SetDefaultMouseSpeed, 0
i := 0
j := 0
StkCount := 1
initPos := [TopLeftCornerX + (FieldWidth / 2), BottomRightCornerY - (FieldHeight * 1.5)]
StackFields := []
While i < 12
{
	while j < 3
	{
		StackFields[StkCount, 1] := initPos[1] + (j * FieldWidth)
		StackFields[StkCount, 2] := initPos[2] - (i * FieldHeight)
		StkCount := StkCount + 1
		j := j + 1
	}
	j := 0
	i := i + 1
}

; For FieldNum, FieldValue in StackFields
;	MsgBox % " Coordinates of Stack-Field #" . FieldNum .  ": " . FieldValue[1] . FieldValue[2]

CurrentStk := 0

OGem() {
	global CraftingField
	Send {Numpad7}
	MouseClick, left, CraftingField[1], CraftingField[2]
}
YGem() {
	global CraftingField
	Send {Numpad8}
	MouseClick, left, CraftingField[1], CraftingField[2]
}
BGem() {
	global CraftingField
	Send {Numpad1}
	MouseClick, left, CraftingField[1], CraftingField[2]
}
RGem() {
	global CraftingField
	Send {Numpad4}
	MouseClick, left, CraftingField[1], CraftingField[2]
}

GGem() {
	global CraftingField
	global FieldWidth
	MouseMove, CraftingField[1]-(2*FieldWidth), CraftingField[2]
	send d
}
WGem() {
	global CraftingField
	Send {Numpad9}
	MouseClick, left, CraftingField[1], CraftingField[2]
}

AddtoStk() {
	global CraftingField
	global CurrentStk
	global StackFields
	if CurrentStk != 0
		{
		Send g
		MouseClickDrag, L, CraftingField[1], CraftingField[2], StackFields[CurrentStk][1], StackFields[CurrentStk][2]
		}
}

MovetoStk() {
	global CraftingField
	global CurrentStk
	global StackFields
	CurrentStk := CurrentStk + 1
	MouseClickDrag, L, CraftingField[1], CraftingField[2], StackFields[CurrentStk][1], StackFields[CurrentStk][2]
}

PopStk() {
	global CraftingField
	global CurrentStk
	global StackFields
	if CurrentStk > 1
		{
		Send g
		MouseClickDrag, L, StackFields[CurrentStk][1], StackFields[CurrentStk][2], StackFields[CurrentStk - 1][1], StackFields[CurrentStk - 1][2]
		CurrentStk := CurrentStk - 1
		}
}

if (CombineMode = True) {
	StrPosEnd := StrLen(ParentStr)
	ElementFound := False
	While ElementFound = False {
		if (SubStr(ParentStr, StrPosEnd, 1) != ")") {
			ElementFound := True
			LastGemPos := StrPosEnd
		}
		StrPosEnd := StrPosEnd - 1
	}
}

StrPos := 1
Parents := []

While StrPos < StrLen(ParentStr) {
	if (SubStr(ParentStr, StrPos, 1) = "(") {
		if ((SubStr(ParentStr, StrPos - 1, 1) = "(") or (StrPos = 1))
			Parents.Insert(False)
		else
			Parents.Insert(True)
	}

	if (SubStr(ParentStr, StrPos, 1) = ")") {
		if (Parents[Parents.MaxIndex()] = True)
			PopStk()
		Parents.remove(Parents.MaxIndex())
	}

	if (SubStr(ParentStr, StrPos, 1) = "o") {
		OGem()
		if (SubStr(ParentStr, StrPos - 1, 1) = "(")
			MovetoStk()
		else
			AddtoStk()
	}

	if (SubStr(ParentStr, StrPos, 1) = "r") {
		RGem()
		if (SubStr(ParentStr, StrPos - 1, 1) = "(")
			MovetoStk()
		else
			AddtoStk()
	}

	if (SubStr(ParentStr, StrPos, 1) = "b") {
		BGem()
		if (SubStr(ParentStr, StrPos - 1, 1) = "(")
			MovetoStk()
		else
			AddtoStk()
	}

	if (SubStr(ParentStr, StrPos, 1) = "y") {
		YGem()
		if (SubStr(ParentStr, StrPos - 1, 1) = "(")
			MovetoStk()
		else
			AddtoStk()
	}
	if (SubStr(ParentStr, StrPos, 1) = "w") {
		WGem()
		if (SubStr(ParentStr, StrPos - 1, 1) = "(")
			MovetoStk()
		else
			AddtoStk()
	}
	if ((SubStr(ParentStr, StrPos, 1) = "g") or (SubStr(ParentStr, StrPos, 1) = "k") or (SubStr(ParentStr, StrPos, 1) = "m")) {
		if (LastGemPos != StrPos)
			GGem()
		else
			MouseClickDrag, L, CraftingField[1]-(2*FieldWidth), CraftingField[2], CraftingField[1], CraftingField[2]
		if (SubStr(ParentStr, StrPos - 1, 1) = "(")
			MovetoStk()
		else
			AddtoStk()
	}

	if ((SubStr(ParentStr, StrPos, 1) < 10) and (SubStr(ParentStr, StrPos, 1) > 1)) {
		if (SubStr(ParentStr, StrPos + 1, 1) = "o")
			OGem()
		if (SubStr(ParentStr, StrPos + 1, 1) = "y")
			YGem()
		if (SubStr(ParentStr, StrPos + 1, 1) = "b")
			BGem()
		if (SubStr(ParentStr, StrPos + 1, 1) = "r")
			RGem()
		if (SubStr(ParentStr, StrPos + 1, 1) = "r")
			WGem()
		if (SubStr(ParentStr, StrPos + 1, 1) = "g") {
			if (LastGemPos != StrPos + 1)
				GGem()
			else
				MouseClickDrag, L, CraftingField[1]-(2*FieldWidth), CraftingField[2], CraftingField[1], CraftingField[2]
		}
		UCount := 1
		While UCount <= SubStr(ParentStr, StrPos + 1, 1) {
			MouseMove, CraftingField[1], CraftingField[2]
			send u
			UCount := UCount + 1
		}

		if (SubStr(ParentStr, StrPos - 1, 1) = "(")
			MovetoStk()
		else
			AddtoStk()
		StrPos := StrPos + 1
	}

	if (SubStr(ParentStr, StrPos, 1) = "a") {
		MouseClickDrag, L, TopLeftCornerX + (FieldWidth / 2), TopLeftCornerY + (FieldHeight / 2), CraftingField[1], CraftingField[2]
		if (SubStr(ParentStr, StrPos - 1, 1) = "(")
			MovetoStk()
		else
			AddtoStk()

	}
	if (SubStr(ParentStr, StrPos, 1) = "s") {
		MouseClickDrag, L, TopLeftCornerX + (FieldWidth * 1.5), TopLeftCornerY + (FieldHeight / 2), CraftingField[1], CraftingField[2]
		if (SubStr(ParentStr, StrPos - 1, 1) = "(")
			MovetoStk()
		else
			AddtoStk()

	}
	if (SubStr(ParentStr, StrPos, 1) = "d") {
		MouseClickDrag, L, TopLeftCornerX + (FieldWidth * 2.5), TopLeftCornerY + (FieldHeight / 2), CraftingField[1], CraftingField[2]
		if (SubStr(ParentStr, StrPos - 1, 1) = "(")
			MovetoStk()
		else
			AddtoStk()

	}
	StrPos := StrPos + 1
}
while CurrentStk > 1 {
	PopStk()
}

Return

; AutoHotkey Version: 1.1x
; Language:       English
; Author:         8thSeaOfRhye
;
;                     #####         Parent2Gem.ahk - Version 2       #####
;
;                     ##### Description of Purpose and Functionality #####
;
; ###            General             ###
; This script translates a String containing the Parenthesis-( i.e. Bracket-)Version of
; a speccing or combining scheme for gemcraft into actual commands for the gems creation.
; Works best in a STANDALONE FLASHPLAYER set to FULLSCREEN.
; It is hopefully easy to use and customize.
; The section which has to be changed is almost right at the top of the following code,
; namely under the command "!C::", and is commented to indicate the exact usage.
;
; The STANDARD HOTKEY is  Alt + c (No shift!!). This corresponds to "!C".
; Check ahkscript.org for Hotkey usage.
;
; CombiningMode is turned on by default. Speccing still works. Suggestion: Don't turn it off...
;
;
; ###  Syntax for the Bracket-Formula ###
;
; Obviously:
; 		r = Red / b = Black / o = orange / y = yellow
;
; Maybe a little less obviously:
;
;		g / k = copy of gem in the BOTTOM-LEFT! corner of the 12*3 craftingfield
;
; Furthermore:   ### New Features ###
;
;		the numerals 2 to 9 followed by any of the above = Corresponding color (or duplicate, respectively), upgraded 1 to 8 times
;
;		Examples: 9o / 2g = Orange upgraded 8 times (grade 9) / Base-gem (BottomLeft corner) upgraded once
;		(Needless to say, the upgrading happens via the "u"-button.)
;
; And:
;
;		a / s / d  =  use (left / middle / right) gem in the top row of the 3*12 craftingfield
;
;		(The order is inspired by the position of the keys on a standard keyboard.
;		 Attention: Those three can't be used in combination with numerals.)

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.
InitialMode := False ; Initialisation
;CoordMode, Mouse, Screen
CurrentCustom := "(g+g)+(g+g)"
LastDDL := 5
;             I
; #####      V V       																					 #########
; #####       V        INSERT THE SCHEME TO BE COMBINED INBETWEEN THE QUTATION-MARKS IN THE LINE BELOW   #########
ParentStr := "(g+g)+(g+g)"

; #####   						The default example is some random 1024 combine							 #########

!V::
	OptionsMenu()
return

OptionsMenu() {
	Global ParentStr
	Global ChosenCombine
	Global ParentNewStr
	Global ChosenIniMode
	Global IsIniChecked
	Global InitialMode
	Global CustomFormula
	Global PGScript
	Global CustomTemp
	Global LastDDL
	Global CurrentCustom
	Global LastDDLTemp
	Global TempReadOnly

	Gui, New,, Options
	GuiHWND := WinExist()

; ################# DDL ######################
	TempReadOnly := ""
	If LastDDL != 5
		TempReadOnly := "readonly"
	Gui, Add, Text,, Choose your desired combine
	Gui, Add, DropDownList, w200 Choose%LastDDL% vChosenCombine gShowCustomField, killgem_amps64-5-gem|killgem_amps64-5-amps|managem_amps256-30_ieee-gem|managem_amps256-30_ieee-amps|Custom
	Gui, Add, Text,, Custom Bracket Formula:        Attention! Syntaxerrors may lead to chaos!
	Gui, Add, Edit, w400 r3 vCustomFormula %TempReadOnly%, %CurrentCustom%

; ################# INITMODE ################

	Gui, Add, Text,, `n`n In order to reset the coordinates check the following option`: `n
	If (InitialMode = False)
		IsIniChecked := ""
	If (InitialMode = True)
		IsIniChecked := "Checked"
	Gui, Add, Checkbox, vChosenIniMode %IsIniChecked%, Initialisation-Mode
	Gui, Add, Text,, If checked, you will be asked for coordinates the next time the CombiningHotkey is pressed.`n CombiningHotkey is Alt C by default.

;###############Wait For Input ##############

	Gui, Add, Button, default, Ok
	Gui, Show
	WinWaitClose, ahk_id %GuiHWND%
	return

;############### SUBS / Labels #############

	ShowCustomField:
		GuiControlGet, StatusOfDll, , ChosenCombine
		if (StatusOfDll = "custom")
			GuiControl, -readonly, CustomFormula
		else
			GuiControl, +readonly, CustomFormula
	return

	ButtonOk:
		Gui, Submit
		if (ChosenCombine = "killgem_amps64-5-gem") {
			ParentNewStr := "((((b+((b+y)+(y+y)))+((b+(b+y))+(b+(b+(b+b)))))+(((b+b)+(b+(y+y)))+(((b+y)+(y+y))+((y+y)+(y+(y+(y+(y+y))))))))+((((b+(b+y))+(b+(y+y)))+((b+(b+y))+(b+(b+(b+(b+b))))))+(((b+(b+y))+(b+(b+(b+b))))+((b+(b+(b+b)))+((b+(b+b))+((b+(b+b))+(b+(b+(b+(b+b))))))))))"
			LastDDL := 1
		}
		if (ChosenCombine = "killgem_amps64-5-amps") {
			ParentNewStr := "((y+y)+(y+(y+y)))"
			LastDDL := 2
		}

		if (ChosenCombine = "managem_amps256-30_ieee-gem") {
			ParentNewStr := "(((((((b+o)+(b+b))+(b+((o+o)+(b+o))))+(((b+o)+(b+b))+((b+b)+(b+(b+(b+(b+b)))))))+((((b+o)+(b+b))+(b+((o+o)+(o+(o+o)))))+((b+((o+o)+(b+o)))+(((o+o)+(b+o))+((o+o)+(o+(o+(o+(o+(o+(o+o)))))))))))+(((((b+o)+(b+b))+(b+((o+o)+(o+(o+o)))))+(((b+o)+(b+b))+((b+b)+(b+(b+(b+(b+b)))))))+((((b+o)+(b+b))+((b+b)+(b+(b+(b+(b+b))))))+(((b+b)+(b+(b+(b+(b+b)))))+((b+(b+(b+(b+b))))+((b+(b+(b+b)))+((b+(b+b))+((b+b)+(b+(b+(b+(b+(b+b)))))))))))))+((((((b+o)+(b+b))+(b+((b+o)+(o+(o+o)))))+(((b+o)+(b+b))+((b+b)+(b+(b+(b+(b+b)))))))+((((b+o)+(b+b))+(b+((b+o)+(o+(o+o)))))+((b+((o+o)+(b+o)))+(((o+o)+(b+o))+((o+(o+o))+(o+(o+(o+(o+(o+(o+o)))))))))))+(((((b+o)+(b+b))+(b+((b+o)+(o+(o+o)))))+((b+((o+o)+(b+o)))+(((b+o)+(o+(o+o)))+((o+(o+o))+(o+(o+(o+(o+(o+(o+o))))))))))+(((b+((o+o)+(b+o)))+((b+(o+o))+((o+o)+(o+(o+(o+(o+(o+o))))))))+((((o+o)+(b+o))+((o+(o+o))+(o+(o+(o+(o+(o+(o+o))))))))+(((o+o)+(o+(o+(o+(o+(o+o))))))+(((o+o)+(o+(o+(o+(o+(o+o))))))+((o+(o+(o+(o+o))))+((o+(o+(o+o)))+((o+(o+o))+((o+(o+o))+(o+(o+(o+(o+(o+(o+(o+o))))))))))))))))))"
			LastDDL := 3
		}

		if (ChosenCombine = "managem_amps256-30_ieee-amps") {
			ParentNewStr := "((((o+o)+(o+o))+((o+o)+(o+(o+(o+o)))))+(((o+o)+(o+(o+(o+o))))+((o+(o+o))+((o+(o+o))+(o+(o+(o+(o+(o+(o+(o+o)))))))))))"
			LastDDL := 4
		}

		if (ChosenCombine = "Custom") {
			ParentNewStr := CustomFormula
			LastDDL := 5
		}

;		if (ChosenCombine = "") {
;			ParentNewStr := ""
;			LastDDL := 1
;		}

		if (ChosenCombine = "")
			ParentNewStr := ParentStr

		FileRead, PGScript, Parent2Gem.ahk
		FileDelete, Parent2Gem.ahk
		ParentNewStr = ParentStr := "%ParentNewStr%"
		PGScript := RegExReplace(PGScript, "ParentStr := ""[A-Za-z0-9()+]*""", ParentNewStr, , 1)

		CustomTemp = CurrentCustom := "%CustomFormula%"
		if (ChosenCombine = "Custom")
			PGScript := RegExReplace(PGScript, "CurrentCustom := "".*""", CustomTemp, , 1)

		LastDDLTemp = LastDDL := %LastDDL%
		PGScript := RegExReplace(PGScript, "LastDDL := [0-9]*", LastDDLTemp, , 1)

		if ((ChosenIniMode = 0) and (InitialMode = True))
			PGScript := RegExReplace(PGScript, "InitialMode := True  `; Init", "InitialMode := False `; Init", , 1)
		if ((ChosenIniMode = 1) and (InitialMode = False))
			PGScript := RegExReplace(PGScript, "InitialMode := False `; Init", "InitialMode := True  `; Init", , 1)

		FileAppend, %PGScript%, Parent2Gem.ahk
		Gui, Destroy
	Reload
}
!C::

CombineMode := True
LastGemPos := 1

TopLeftCornerX := 1590 				;  ####### ENTER THE COORDINATES OF THE 3*12 CRAFTINGFIELD ON YOUR SCREEN #########
TopLeftCornerY := 338				;	###### If you don't know how to obtain those values, you'd better  ########
BottomRightCornerX := 1436			;    ##### ask somebody. They don't have to be really precise.     #######
BottomRightCornerY := 686			;	  #### AND THAT'S IT! The script should work for you now!  ######

if (InitialMode = True) {
	FileRead, PGScript, Parent2Gem.ahk
	FileDelete, Parent2Gem.ahk
	MsgBox Place your mouse over the top-left corner of the 12*3 craftingfield and press ENTER
		MouseGetPos, TLCX, TLCY
		PGScript := RegExReplace(PGScript, "TopLeftCornerX := [0-9]+", "TopLeftCornerX := " TLCX, , 1)
		PGScript := RegExReplace(PGScript, "TopLeftCornerY := [0-9]+", "TopLeftCornerY := " TLCY, , 1)
	MsgBox Place your mouse over the bottom-right corner of the 12*3 craftingfield and press ENTER
		MouseGetPos, BRCX, BRCY
		PGScript := RegExReplace(PGScript, "BottomRightCornerX := [0-9]+", "BottomRightCornerX := "BRCX, , 1)
		PGScript := RegExReplace(PGScript, "BottomRightCornerY := [0-9]+", "BottomRightCornerY := "BRCY, , 1)
		PGScript := RegExReplace(PGScript, "InitialMode := True  `; Init", "InitialMode := False `; Init", , 1)
	FileAppend, %PGScript%, Parent2Gem.ahk

	MsgBox The Script has been initialised and will be reloaded!

	ExitApp
}
FieldWidth := (BottomRightCornerX - TopLeftCornerX) / 3
FieldHeight := (BottomRightCornerY - TopLeftCornerY) / 12
CraftingField := [BottomRightCornerX -(FieldWidth / 2), BottomRightCornerY -(FieldHeight / 2)]

SetDefaultMouseSpeed, 0
i := 0
j := 0
StkCount := 1
initPos := [TopLeftCornerX + (FieldWidth / 2), BottomRightCornerY - (FieldHeight * 1.5)]
StackFields := []
While i < 12
{
	while j < 3
	{
		StackFields[StkCount, 1] := initPos[1] + (j * FieldWidth)
		StackFields[StkCount, 2] := initPos[2] - (i * FieldHeight)
		StkCount := StkCount + 1
		j := j + 1
	}
	j := 0
	i := i + 1
}

; For FieldNum, FieldValue in StackFields
;	MsgBox % " Coordinates of Stack-Field #" . FieldNum .  ": " . FieldValue[1] . FieldValue[2]

CurrentStk := 0

OGem() {
	global CraftingField
	Send {Numpad7}
	MouseClick, left, CraftingField[1], CraftingField[2]
}
YGem() {
	global CraftingField
	Send {Numpad8}
	MouseClick, left, CraftingField[1], CraftingField[2]
}
BGem() {
	global CraftingField
	Send {Numpad1}
	MouseClick, left, CraftingField[1], CraftingField[2]
}
RGem() {
	global CraftingField
	Send {Numpad4}
	MouseClick, left, CraftingField[1], CraftingField[2]
}

GGem() {
	global CraftingField
	global FieldWidth
	MouseMove, CraftingField[1]-(2*FieldWidth), CraftingField[2]
	send d
}
WGem() {
	global CraftingField
	Send {Numpad9}
	MouseClick, left, CraftingField[1], CraftingField[2]
}

AddtoStk() {
	global CraftingField
	global CurrentStk
	global StackFields
	if CurrentStk != 0
		{
		Send g
		MouseClickDrag, L, CraftingField[1], CraftingField[2], StackFields[CurrentStk][1], StackFields[CurrentStk][2]
		}
}

MovetoStk() {
	global CraftingField
	global CurrentStk
	global StackFields
	CurrentStk := CurrentStk + 1
	MouseClickDrag, L, CraftingField[1], CraftingField[2], StackFields[CurrentStk][1], StackFields[CurrentStk][2]
}

PopStk() {
	global CraftingField
	global CurrentStk
	global StackFields
	if CurrentStk > 1
		{
		Send g
		MouseClickDrag, L, StackFields[CurrentStk][1], StackFields[CurrentStk][2], StackFields[CurrentStk - 1][1], StackFields[CurrentStk - 1][2]
		CurrentStk := CurrentStk - 1
		}
}

if (CombineMode = True) {
	StrPosEnd := StrLen(ParentStr)
	ElementFound := False
	While ElementFound = False {
		if (SubStr(ParentStr, StrPosEnd, 1) != ")") {
			ElementFound := True
			LastGemPos := StrPosEnd
		}
		StrPosEnd := StrPosEnd - 1
	}
}

StrPos := 1
Parents := []

While StrPos < StrLen(ParentStr) {
	if (SubStr(ParentStr, StrPos, 1) = "(") {
		if ((SubStr(ParentStr, StrPos - 1, 1) = "(") or (StrPos = 1))
			Parents.Insert(False)
		else
			Parents.Insert(True)
	}

	if (SubStr(ParentStr, StrPos, 1) = ")") {
		if (Parents[Parents.MaxIndex()] = True)
			PopStk()
		Parents.remove(Parents.MaxIndex())
	}

	if (SubStr(ParentStr, StrPos, 1) = "o") {
		OGem()
		if (SubStr(ParentStr, StrPos - 1, 1) = "(")
			MovetoStk()
		else
			AddtoStk()
	}

	if (SubStr(ParentStr, StrPos, 1) = "r") {
		RGem()
		if (SubStr(ParentStr, StrPos - 1, 1) = "(")
			MovetoStk()
		else
			AddtoStk()
	}

	if (SubStr(ParentStr, StrPos, 1) = "b") {
		BGem()
		if (SubStr(ParentStr, StrPos - 1, 1) = "(")
			MovetoStk()
		else
			AddtoStk()
	}

	if (SubStr(ParentStr, StrPos, 1) = "y") {
		YGem()
		if (SubStr(ParentStr, StrPos - 1, 1) = "(")
			MovetoStk()
		else
			AddtoStk()
	}
	if (SubStr(ParentStr, StrPos, 1) = "w") {
		WGem()
		if (SubStr(ParentStr, StrPos - 1, 1) = "(")
			MovetoStk()
		else
			AddtoStk()
	}
	if ((SubStr(ParentStr, StrPos, 1) = "g") or (SubStr(ParentStr, StrPos, 1) = "k") or (SubStr(ParentStr, StrPos, 1) = "m")) {
		if (LastGemPos != StrPos)
			GGem()
		else
			MouseClickDrag, L, CraftingField[1]-(2*FieldWidth), CraftingField[2], CraftingField[1], CraftingField[2]
		if (SubStr(ParentStr, StrPos - 1, 1) = "(")
			MovetoStk()
		else
			AddtoStk()
	}

	if ((SubStr(ParentStr, StrPos, 1) < 10) and (SubStr(ParentStr, StrPos, 1) > 1)) {
		if (SubStr(ParentStr, StrPos + 1, 1) = "o")
			OGem()
		if (SubStr(ParentStr, StrPos + 1, 1) = "y")
			YGem()
		if (SubStr(ParentStr, StrPos + 1, 1) = "b")
			BGem()
		if (SubStr(ParentStr, StrPos + 1, 1) = "r")
			RGem()
		if (SubStr(ParentStr, StrPos + 1, 1) = "r")
			WGem()
		if (SubStr(ParentStr, StrPos + 1, 1) = "g") {
			if (LastGemPos != StrPos + 1)
				GGem()
			else
				MouseClickDrag, L, CraftingField[1]-(2*FieldWidth), CraftingField[2], CraftingField[1], CraftingField[2]
		}
		UCount := 1
		While UCount <= SubStr(ParentStr, StrPos + 1, 1) {
			MouseMove, CraftingField[1], CraftingField[2]
			send u
			UCount := UCount + 1
		}

		if (SubStr(ParentStr, StrPos - 1, 1) = "(")
			MovetoStk()
		else
			AddtoStk()
		StrPos := StrPos + 1
	}

	if (SubStr(ParentStr, StrPos, 1) = "a") {
		MouseClickDrag, L, TopLeftCornerX + (FieldWidth / 2), TopLeftCornerY + (FieldHeight / 2), CraftingField[1], CraftingField[2]
		if (SubStr(ParentStr, StrPos - 1, 1) = "(")
			MovetoStk()
		else
			AddtoStk()

	}
	if (SubStr(ParentStr, StrPos, 1) = "s") {
		MouseClickDrag, L, TopLeftCornerX + (FieldWidth * 1.5), TopLeftCornerY + (FieldHeight / 2), CraftingField[1], CraftingField[2]
		if (SubStr(ParentStr, StrPos - 1, 1) = "(")
			MovetoStk()
		else
			AddtoStk()

	}
	if (SubStr(ParentStr, StrPos, 1) = "d") {
		MouseClickDrag, L, TopLeftCornerX + (FieldWidth * 2.5), TopLeftCornerY + (FieldHeight / 2), CraftingField[1], CraftingField[2]
		if (SubStr(ParentStr, StrPos - 1, 1) = "(")
			MovetoStk()
		else
			AddtoStk()

	}
	StrPos := StrPos + 1
}
while CurrentStk > 1 {
	PopStk()
}

Return


LV_ModifyCol AutoHdr

LV_ModifyCol AutoHdr

VimDConfig:
    vim.SetPlugin("VimDConfig", "Array", "0.1", "VimDesktop的配置界面")
    vim.SetAction("<VimDConfig_Plugin>", "显示 VimDesktop 插件信息")
    vim.SetAction("<VimDConfig_Keymap>", "显示 VimDesktop 热键信息")
    vim.SetAction("<VimDConfig_EditConfig>", "打开 VimDesktop 配置文件")
return

<VimDConfig_Plugin>:
{
    GUI, VimDConfig_plugin:Destroy
    GUI, VimDConfig_plugin:Default
    GUI, VimDConfig_plugin:Font, s10, Microsoft YaHei

    GUI, VimDConfig_plugin:Add, GroupBox, x10 y10 w170 h440, 插件 &P
    GUI, VimDConfig_plugin:Add, ListView, x20 y35 w150 h400 grid altsubmit gVimDConfig_LoadActions, 名称
    for plugin, obj in vim.PluginList
        LV_Add("", plugin)

    GUI, VimDConfig_plugin:Add, GroupBox, x10 y460 w170 h70, 过滤 &F
    GUI, VimDConfig_plugin:Add, Edit, x20 y490 gsearch_plugin v_search

    GUI, VimDConfig_plugin:Add, GroupBox, x190 y10 w650 h520, 动作 &A
    GUI, VimDConfig_plugin:Add, ListView, glistview x200 y35 w630 h482 grid altsubmit, 序号|动作|描述（双击进入文件）

    LV_ModifyCol(1, "center")
    LV_ModifyCol(2, "left 250")
    LV_ModifyCol(3, "AutoHdr")
    GUI, VimDConfig_plugin:Show
    return
}

VimDConfig_LoadActions:
{
    If A_GuiEvent = I
    {
        if not InStr(ErrorLevel, "S", true)
        {
            return
        }

        GUI, VimDConfig_plugin:ListView, sysListview321
        LV_GetText(plugin, A_EventInfo)
        GUI, VimDConfig_plugin:Default
        GUI, VimDConfig_plugin:ListView, sysListview322
        idx := 1
        LV_Delete()

        global current_plugin := ""
        for action, type in vim.ActionFromPlugin
        {
            If type = %plugin%
            {
                Desc := vim.GetAction(action)
                LV_Add("", idx, action, Desc.Comment)
                current_plugin .= idx "`t" action "`t" Desc.Comment "`n"
                idx++
            }
        }
    }
    return
}

<VimDConfig_Keymap>:
{
    menu, VimDConfig_keymap_menu, add
    menu, VimDConfig_keymap_menu, add, &Exit, VimDConfig_keymap_exit

    GUI, VimDConfig_keymap:Destroy
    GUI, VimDConfig_keymap:Default
    GUI, VimDConfig_keymap:Font, s10, Microsoft YaHei

    GUI, VimDConfig_keymap:Add, GroupBox, x10 y10 w200 h269, 插件 &P
    GUI, VimDConfig_keymap:Add, ListBox, x20 y35 w180 R12 center gVimDConfig_keymap_loadmodelist

    GUI, VimDConfig_keymap:Add, GroupBox, x10 y290 w200 h135, 模式 &M
    GUI, VimDConfig_keymap:Add, ListBox, x20 y315 w180 R5 center gVimDConfig_keymap_loadhotkey

    GUI, VimDConfig_keymap:Add, GroupBox, x10 y435 w200 h61, 过滤 &F
    GUI, VimDConfig_keymap:Add, Edit, gsearch_keymap v_search x20 y460 w180 h25

    GUI, VimDConfig_keymap:Add, GroupBox, x225 y10 w650 h486, 映射 &K
    GUI, VimDConfig_keymap:Add, Listview, glistview x235 y36 w630 h450 grid, 热键|动作（双击定位，右键双击编辑）|描述

    LV_ModifyCol(1, "left 100")
    LV_ModifyCol(2, "left 250")
    LV_ModifyCol(3, "AutoHdr")

    VimDConfig_keymap_loadwinlist()
    VimDConfig_keymap_loadhotkey(VimDConfig_keymap_loadmodelist(thiswin))

    GUI, VimDConfig_keymap:show
    ControlFocus, Edit1, A
    return
}

<VimDConfig_EditConfig>:
    Run, %A_ScriptDir%\vimd.ini
return

VimDConfig_keymap_exit:
{
    GUI, VimDConfig_keymap:Destroy
    return
}

VimDConfig_keymap_loadwinlist()
{
    global vim
    list := "|全局"
    GUI, VimDConfig_keymap:Default
    for win, obj in vim.WinList
    {
        if vim.ExcludeWinList[win]
        {
            continue
        }

        ; Convert class name TTOTAL_CMD to plugin name TotalCommander
        if (win = "TTOTAL_CMD")
        {
            win := "TotalCommander"
        }
        list .= "|" win
    }
    GuiControl, , ListBox1, %list%
}

VimDConfig_keymap_loadmodelist:
    VimDConfig_keymap_loadmodelist()
    GUI, VimDConfig_keymap:Default
    LV_delete()
    GuiControl, Choose, ListBox2, |normal
return

VimDConfig_keymap_loadmodelist(win = "")
{
    global vim
    GUI, VimDConfig_keymap:Default
    If not strlen(win)
        ControlGet, win, Choice, , ListBox1
    If win = 全局
        winObj := vim.GetWin()
    Else
        winObj := vim.GetWin(win)
    for mode, obj in winObj.modeList
        mlist .= "|" mode
    GuiControl, , ListBox2, %mlist%
    return win
}

VimDConfig_keymap_loadhotkey:
    GUI, VimDConfig_keymap:Default
    ControlGet, win, Choice, , ListBox1
    win := RegExMatch(win, "^全局$") ? "" : win

    ; Convert plugin name TotalCommander to class name TTOTAL_CMD
    if (win = "TotalCommander")
    {
        win := "TTOTAL_CMD"
    }

    ControlGet, mode, Choice, , ListBox2
    VimDConfig_keymap_loadhotkey(win, mode)
return

VimDConfig_keymap_loadhotkey(win, mode = "")
{
    global vim
    global current_keymap := ""
    If strlen(mode)
    {
        winObj  := vim.GetWin(win)
        modeobj := winObj.modeList[mode]
    }
    Else
        modeobj := vim.GetMode(win)
    GUI, VimDConfig_keymap:Default
    LV_delete()
    for key, i in modeobj.keymapList
    {
        ; Type = 1 : Function
        if (vim.GetAction(i).Type = 1)
        {
            ActionDescList := vim.GetAction(i).Comment
            actionDesc := StrSplit(%ActionDescList%[key], "|")
            LV_ADD("", Key, actionDesc[1], actionDesc[2])
            current_keymap .= Key "`t" actionDesc[1] "`t" actionDesc[2] "`n"
        }
        else
        {
            LV_Add("", RegExReplace(Key, "<S-(.*)>", "$1"), i, vim.GetAction(i).Comment)
            current_keymap .= Key "`t" i "`t" vim.GetAction(i).Comment "`n"
        }
    }
}

listview:
    if A_GuiEvent = DoubleClick
    {
        ;~ ToolTip You double-clicked row number %A_EventInfo%.
        LV_GetText(SelectedAction, A_EventInfo, 2)
        LV_GetText(SelectedDesc, A_EventInfo, 3)
        SearchFileForEdit(SelectedAction, SelectedDesc, false)
    }
    else if A_GuiEvent = R
    {
        LV_GetText(SelectedAction, A_EventInfo, 2)
        LV_GetText(SelectedDesc, A_EventInfo, 3)
        SearchFileForEdit(SelectedAction, SelectedDesc, true)
    }

return

SearchFileForEdit(Action, Desc, EditKeyMapping)
{
    IsUserCmd := RegExMatch(Action, "^(run|key|dir|tccmd|wshkey)$")
    if (IsUserCmd || EditKeyMapping)
    {
        SearchLine := "=" Action
        if (IsUserCmd || Action == "function")
        {
            SearchLine := Action "|" Desc
        }

        Loop, Read, %A_ScriptDir%\vimd.ini
        {
            if (InStr(A_LoopReadLine, SearchLine))
            {
                EditFile(A_ScriptDir "\vimd.ini", A_Index)
                return
            }
        }

        EditFile(A_ScriptDir "\vimd.ini")
        return
    }

    label := Action ":"
    if (Action == "function")
    {
        label := Desc
    }

    Loop, %A_ScriptDir%\plugins\*.ahk, , 1
    {
        Loop, Read, %A_LoopFileFullPath%
        {
            if (InStr(A_LoopReadLine, label) == 1)
            {
                EditFile(A_LoopFileFullPath, A_Index)
                return
            }
        }
    }

    Loop, %A_ScriptDir%\core\*.ahk, , 1
    {
        Loop, Read, %A_LoopFileFullPath%
        {
            if (InStr(A_LoopReadLine, label) = 1)
            {
                EditFile(A_LoopFileFullPath, A_Index)
                return
            }
        }
    }
}

EditFile(editPath, line := 1)
{
    editorArgs := {}
    editorArgs["notepad"] := "/g $line $file"
    editorArgs["notepad2"] := "/g $line $file"
    editorArgs["sublime_text"] := "$file:$line"
    editorArgs["vim"] := "+$line $file"
    editorArgs["gvim"] := "--remote-silent-tab +$line $file"
    editorArgs["everedit"] := "-n$line $file"
    editorArgs["notepad++"] := "-n$line $file"
    editorArgs["EmEditor"] := "-l $line $file"
    editorArgs["uedit32"] := "$file/$line"
    editorArgs["Editplus"] := "$file -cursor $line"
    editorArgs["textpad"] := "$file($line)"
    editorArgs["pspad"] := "$file /$line"
    editorArgs["ConTEXT"] := "$file /g1:$line"
    editorArgs["scite"] := "$file -goto:$line"

    Global editor

    If not FileExist(editor)
    {
        MsgBox, 请配置 vimd.ini 中 [config] 中的 editor ，并重启 vimd ！
        return
    }

    ; 根据编辑器 exe 名称获取打开参数
    SplitPath, editor, , , OutExtension, OutNameNoExt
    args := editorArgs[OutNameNoExt]
    StringReplace, args, args, $line, %line%
    StringReplace, args, args, $file, "%editPath%"
    target := editor " " args
    if (OutExtension = "sh")
    {
        target := "sh.exe " target
    }

    run, %target%
}

search_keymap:
    global current_keymap
    search_to_display(current_keymap)
return

search_plugin:
    global current_plugin
    search_to_display(current_plugin)
return

search_to_display(lines)
{
    Gui Submit, nohide
    GuiControlGet, OutputVar, , _search

    text := StrSplit(lines, "`n")

    LV_Delete() ; 清理不掉，第二次加载后，都成了重复的了，不知道怎么处理
    GuiControl, -Redraw, listview ; 重新启用重绘 (上面把它禁用了)
    for k, v in text
    {
        if v =
            continue
        if Instr(v, OutputVar)
        {
            list := StrSplit(v, "`t")
            LV_Add("", list[1], list[2], list[3])
        }
    }
    GuiControl, +Redraw, listview ; 重新启用重绘 (上面把它禁用了)
}

VimDConfig:
    vim.SetPlugin("VimDConfig", "Array", "0.1", "VimDesktop的配置界面")
    vim.SetAction("<VimDConfig_Plugin>", "显示 VimDesktop 插件信息")
    vim.SetAction("<VimDConfig_Keymap>", "显示 VimDesktop 热键信息")
    vim.SetAction("<VimDConfig_EditConfig>", "打开 VimDesktop 配置文件")
return

<VimDConfig_Plugin>:
{
    GUI, VimDConfig_plugin:Destroy
    GUI, VimDConfig_plugin:Default
    GUI, VimDConfig_plugin:Font, s10, Microsoft YaHei

    GUI, VimDConfig_plugin:Add, GroupBox, x10 y10 w170 h440, 插件 &P
    GUI, VimDConfig_plugin:Add, ListView, x20 y35 w150 h400 grid altsubmit gVimDConfig_LoadActions, 名称
    for plugin, obj in vim.PluginList
        LV_Add("", plugin)

    GUI, VimDConfig_plugin:Add, GroupBox, x10 y460 w170 h70, 过滤 &F
    GUI, VimDConfig_plugin:Add, Edit, x20 y490 gsearch_plugin v_search

    GUI, VimDConfig_plugin:Add, GroupBox, x190 y10 w650 h520, 动作 &A
    GUI, VimDConfig_plugin:Add, ListView, glistview x200 y35 w630 h482 grid altsubmit, 序号|动作|描述（双击进入文件）

    LV_ModifyCol(1, "center")
    LV_ModifyCol(2, "left 250")
    LV_ModifyCol(3, "left 400")
    GUI, VimDConfig_plugin:Show
    return
}

VimDConfig_LoadActions:
{
    If A_GuiEvent = I
    {
        if not InStr(ErrorLevel, "S", true)
        {
            return
        }

        GUI, VimDConfig_plugin:ListView, sysListview321
        LV_GetText(plugin, A_EventInfo)
        GUI, VimDConfig_plugin:Default
        GUI, VimDConfig_plugin:ListView, sysListview322
        idx := 1
        LV_Delete()

        global current_plugin := ""
        for action, type in vim.ActionFromPlugin
        {
            If type = %plugin%
            {
                Desc := vim.GetAction(action)
                LV_Add("", idx, action, Desc.Comment)
                current_plugin .= idx "`t" action "`t" Desc.Comment "`n"
                idx++
            }
        }
    }
    return
}

<VimDConfig_Keymap>:
{
    menu, VimDConfig_keymap_menu, add
    menu, VimDConfig_keymap_menu, add, &Exit, VimDConfig_keymap_exit

    GUI, VimDConfig_keymap:Destroy
    GUI, VimDConfig_keymap:Default
    GUI, VimDConfig_keymap:Font, s10, Microsoft YaHei

    GUI, VimDConfig_keymap:Add, GroupBox, x10 y10 w200 h269, 插件 &P
    GUI, VimDConfig_keymap:Add, ListBox, x20 y35 w180 R12 center gVimDConfig_keymap_loadmodelist

    GUI, VimDConfig_keymap:Add, GroupBox, x10 y290 w200 h135, 模式 &M
    GUI, VimDConfig_keymap:Add, ListBox, x20 y315 w180 R5 center gVimDConfig_keymap_loadhotkey

    GUI, VimDConfig_keymap:Add, GroupBox, x10 y435 w200 h61, 过滤 &F
    GUI, VimDConfig_keymap:Add, Edit, gsearch_keymap v_search x20 y460 w180 h25

    GUI, VimDConfig_keymap:Add, GroupBox, x225 y10 w650 h486, 映射 &K
    GUI, VimDConfig_keymap:Add, Listview, glistview x235 y36 w630 h450 grid, 热键|动作（双击定位，右键双击编辑）|描述

    LV_ModifyCol(1, "left 100")
    LV_ModifyCol(2, "left 250")
    LV_ModifyCol(3, "left 400")

    VimDConfig_keymap_loadwinlist()
    VimDConfig_keymap_loadhotkey(VimDConfig_keymap_loadmodelist(thiswin))

    GUI, VimDConfig_keymap:show
    ControlFocus, Edit1, A
    return
}

<VimDConfig_EditConfig>:
    Run, %A_ScriptDir%\vimd.ini
return

VimDConfig_keymap_exit:
{
    GUI, VimDConfig_keymap:Destroy
    return
}

VimDConfig_keymap_loadwinlist()
{
    global vim
    list := "|全局"
    GUI, VimDConfig_keymap:Default
    for win, obj in vim.WinList
    {
        if vim.ExcludeWinList[win]
        {
            continue
        }

        ; Convert class name TTOTAL_CMD to plugin name TotalCommander
        if (win = "TTOTAL_CMD")
        {
            win := "TotalCommander"
        }
        list .= "|" win
    }
    GuiControl, , ListBox1, %list%
}

VimDConfig_keymap_loadmodelist:
    VimDConfig_keymap_loadmodelist()
    GUI, VimDConfig_keymap:Default
    LV_delete()
    GuiControl, Choose, ListBox2, |normal
return

VimDConfig_keymap_loadmodelist(win = "")
{
    global vim
    GUI, VimDConfig_keymap:Default
    If not strlen(win)
        ControlGet, win, Choice, , ListBox1
    If win = 全局
        winObj := vim.GetWin()
    Else
        winObj := vim.GetWin(win)
    for mode, obj in winObj.modeList
        mlist .= "|" mode
    GuiControl, , ListBox2, %mlist%
    return win
}

VimDConfig_keymap_loadhotkey:
    GUI, VimDConfig_keymap:Default
    ControlGet, win, Choice, , ListBox1
    win := RegExMatch(win, "^全局$") ? "" : win

    ; Convert plugin name TotalCommander to class name TTOTAL_CMD
    if (win = "TotalCommander")
    {
        win := "TTOTAL_CMD"
    }

    ControlGet, mode, Choice, , ListBox2
    VimDConfig_keymap_loadhotkey(win, mode)
return

VimDConfig_keymap_loadhotkey(win, mode = "")
{
    global vim
    global current_keymap := ""
    If strlen(mode)
    {
        winObj  := vim.GetWin(win)
        modeobj := winObj.modeList[mode]
    }
    Else
        modeobj := vim.GetMode(win)
    GUI, VimDConfig_keymap:Default
    LV_delete()
    for key, i in modeobj.keymapList
    {
        ; Type = 1 : Function
        if (vim.GetAction(i).Type = 1)
        {
            ActionDescList := vim.GetAction(i).Comment
            actionDesc := StrSplit(%ActionDescList%[key], "|")
            LV_ADD("", Key, actionDesc[1], actionDesc[2])
            current_keymap .= Key "`t" actionDesc[1] "`t" actionDesc[2] "`n"
        }
        else
        {
            LV_Add("", RegExReplace(Key, "<S-(.*)>", "$1"), i, vim.GetAction(i).Comment)
            current_keymap .= Key "`t" i "`t" vim.GetAction(i).Comment "`n"
        }
    }
}

listview:
    if A_GuiEvent = DoubleClick
    {
        ;~ ToolTip You double-clicked row number %A_EventInfo%.
        LV_GetText(SelectedAction, A_EventInfo, 2)
        LV_GetText(SelectedDesc, A_EventInfo, 3)
        SearchFileForEdit(SelectedAction, SelectedDesc, false)
    }
    else if A_GuiEvent = R
    {
        LV_GetText(SelectedAction, A_EventInfo, 2)
        LV_GetText(SelectedDesc, A_EventInfo, 3)
        SearchFileForEdit(SelectedAction, SelectedDesc, true)
    }

return

SearchFileForEdit(Action, Desc, EditKeyMapping)
{
    IsUserCmd := RegExMatch(Action, "^(run|key|dir|tccmd|wshkey)$")
    if (IsUserCmd || EditKeyMapping)
    {
        SearchLine := "=" Action
        if (IsUserCmd || Action == "function")
        {
            SearchLine := Action "|" Desc
        }

        Loop, Read, %A_ScriptDir%\vimd.ini
        {
            if (InStr(A_LoopReadLine, SearchLine))
            {
                EditFile(A_ScriptDir "\vimd.ini", A_Index)
                return
            }
        }

        EditFile(A_ScriptDir "\vimd.ini")
        return
    }

    label := Action ":"
    if (Action == "function")
    {
        label := Desc
    }

    Loop, %A_ScriptDir%\plugins\*.ahk, , 1
    {
        Loop, Read, %A_LoopFileFullPath%
        {
            if (InStr(A_LoopReadLine, label) == 1)
            {
                EditFile(A_LoopFileFullPath, A_Index)
                return
            }
        }
    }

    Loop, %A_ScriptDir%\core\*.ahk, , 1
    {
        Loop, Read, %A_LoopFileFullPath%
        {
            if (InStr(A_LoopReadLine, label) = 1)
            {
                EditFile(A_LoopFileFullPath, A_Index)
                return
            }
        }
    }
}

EditFile(editPath, line := 1)
{
    editorArgs := {}
    editorArgs["notepad"] := "/g $line $file"
    editorArgs["notepad2"] := "/g $line $file"
    editorArgs["sublime_text"] := "$file:$line"
    editorArgs["vim"] := "+$line $file"
    editorArgs["gvim"] := "--remote-silent-tab +$line $file"
    editorArgs["everedit"] := "-n$line $file"
    editorArgs["notepad++"] := "-n$line $file"
    editorArgs["EmEditor"] := "-l $line $file"
    editorArgs["uedit32"] := "$file/$line"
    editorArgs["Editplus"] := "$file -cursor $line"
    editorArgs["textpad"] := "$file($line)"
    editorArgs["pspad"] := "$file /$line"
    editorArgs["ConTEXT"] := "$file /g1:$line"
    editorArgs["scite"] := "$file -goto:$line"

    Global editor

    If not FileExist(editor)
    {
        MsgBox, 请配置 vimd.ini 中 [config] 中的 editor ，并重启 vimd ！
        return
    }

    ; 根据编辑器 exe 名称获取打开参数
    SplitPath, editor, , , OutExtension, OutNameNoExt
    args := editorArgs[OutNameNoExt]
    StringReplace, args, args, $line, %line%
    StringReplace, args, args, $file, "%editPath%"
    target := editor " " args
    if (OutExtension = "sh")
    {
        target := "sh.exe " target
    }

    run, %target%
}

search_keymap:
    global current_keymap
    search_to_display(current_keymap)
return

search_plugin:
    global current_plugin
    search_to_display(current_plugin)
return

search_to_display(lines)
{
    Gui Submit, nohide
    GuiControlGet, OutputVar, , _search

    text := StrSplit(lines, "`n")

    LV_Delete() ; 清理不掉，第二次加载后，都成了重复的了，不知道怎么处理
    GuiControl, -Redraw, listview ; 重新启用重绘 (上面把它禁用了)
    for k, v in text
    {
        if v =
            continue
        if Instr(v, OutputVar)
        {
            list := StrSplit(v, "`t")
            LV_Add("", list[1], list[2], list[3])
        }
    }
    GuiControl, +Redraw, listview ; 重新启用重绘 (上面把它禁用了)
}