Code style

Code style

; 初始化class_Vim

vim_Init:
    #UseHook
    SetKeyDelay, -1
return

; 用于热键映射
vim_Key:
    vim.Key()
return

; 用于热键超时
vim_TimeOut:
    vim.IsTimeOut()
return

; 用于Count计数
Internal:
    __v.SetPlugin("Internal", "Array", "0.1", "内置插件")
    __v.SetAction("<1>", "数字 1")
    __v.SetAction("<2>", "数字 2")
    __v.SetAction("<3>", "数字 3")
    __v.SetAction("<4>", "数字 4")
    __v.SetAction("<5>", "数字 5")
    __v.SetAction("<6>", "数字 6")
    __v.SetAction("<7>", "数字 7")
    __v.SetAction("<8>", "数字 8")
    __v.SetAction("<9>", "数字 9")
    __v.SetAction("<0>", "数字 0")
    __v.SetAction("<>", "空操作")
    __v.SetAction("<Pass>", "空操作")
    __v.SetAction("<Default>", "恢复默认")
    __v := ""
return

<1>:
<2>:
<3>:
<4>:
<5>:
<6>:
<7>:
<8>:
<9>:
<0>:
<>:
<Pass>:
<Default>:
return

Class_vim()
{
    global __v
    GoSub, Vim_Init
    __v := v := new __vim
    __v.LoadPlugin("Internal")
    return v
}

GetLastAction()
{
    global __vimLastAction
    return __vimLastAction
}

ShowInfo()
{
    Global vim
    obj := vim.GetMore(true)
    winObj := vim.GetWin(vim.LastFoundWin)
    if winObj.Count
        np .= winObj.Count
    Loop, % obj.MaxIndex()
    {
        act := vim.GetAction(obj[A_Index]["Action"])

        ; Type = 1 : Function
        if (act.Type = 1)
        {
            ActionDescList := act.Comment
            Key := obj[A_Index]["key"]
            np .= Key "`t" %ActionDescList%[Key] "`n"
        }
        else
        {
            np .= obj[A_Index]["key"] "`t" act.Comment "`n"
        }

        if (A_Index = 1)
            np .= "=====================`n"
    }
    MouseGetPos, posx, posy, A
    posx += 40
    posy += 40
    Tooltip, %np%, %posx%, %posy%
}

HideInfo()
{
    ; 当屏幕有非快捷键补全帮助信息时，不清理
    Global showToolTipStatus
    if (!showToolTipStatus)
    {
        Tooltip
    }
}

; 定义数据结构
; Class __vim {{{1
Class __vim
{
    __new()
    {
        this.PluginList := []
        this.WinList    := []
        this.WinInfo    := []
        this.ActionList := []
        this.ActionFromPlugin := []
        this.ExcludeWinList := []
        this.winGlobal  := new __win
        this.ErrorCode  := 0
        tihs.ActionFromPluginName := ""
        this.LastFoundWin := ""
    }

    ; LoadPlugin(PluginName) {{{2
    ; 用于注册插件
    LoadPlugin(PluginName)
    {
        if this.PluginList[PluginName]
            return this.PluginList[PluginName]
        p := new __Plugin(PluginName)
        this.PluginList[PluginName] := p
        back := this.ActionFromPluginName
        this.ActionFromPluginName := PluginName
        p.CheckSub()
        if p.Error
        {
            MsgBox load plugin "%PluginName%" error
            this.ActionFromPluginName := back
        }
    }

    ; SetPlugin(PluginName, Author = "", Ver = "", Comment = "") {{{2
    ; 设置Plugin信息
    SetPlugin(PluginName, Author = "", Ver = "", Comment = "")
    {
        p := this.PluginList[PluginName]
        p.Author := Author
        p.Ver := Ver
        p.Comment := Comment
    }

    ; GetPlugin(PluginName) {{{2
    ; 获取Plugin信息
    GetPlugin(PluginName)
    {
        return this.PluginList[PluginName]
    }

    ; Comment(action, desc, complex=1) {{{2
    ; 兼容老版本的vimcore.ahk
    Comment(action, desc = "", complex=1)
    {
        act := this.SetAction(Action, Desc)
        if not complex ; 不允许多次运行
            act.SetMaxTimes(1)
        return act
    }

    ; SetAction(Name, Comment) {{{2
    ; 用于为Action(动作)进行注释
    SetAction(Name, Comment = "")
    {
        if this.ActionList[Name]
            ra := This.ActionList[Name]
        else
            ra := This.ActionList[Name] := new __Action(Name, Comment)
        This.ActionFromPlugin[Name] := this.ActionFromPluginName
        return ra
    }

    ; GetAction(Name) {{{2
    ; 获取Action的信息
    GetAction(Name)
    {
        return this.ActionList[Name]
    }

    ; SetWin(winName, class, filepath, title) {{{2
    ; 添加win成员
    SetWin(winName, class, filepath = "", title = "")
    {
        if this.WinList[winName]
            rw := this.WinList[winName]
        else
            rw := this.WinList[winName] := new __win(class, filepath, title)
        this.WinInfo["class`t"class]       := winName
        this.WinInfo["filepath`t"filepath] := winName
        this.WinInfo["title`t"title]       := winName
        return rw
    }

    ; GetWin(winName) {{{2
    GetWin(winName = "")
    {
        if strlen(winName)
            return this.WinList[winName]
        else
            return this.winGlobal
    }

    ; CheckWin() {{{2
    CheckWin()
    {
        /*
        WinGetTitle, t, A
        if Strlen(winName := this.WinInfo["title`t"t])
            return winName
        */

        WinGet, f, ProcessName, A
        if Strlen(winName := this.WinInfo["filepath`t"f])
            return winName
        WinGetClass, c, A
        if Strlen(winName := this.WinInfo["class`t"c])
            return winName
    }

    ; mode(mode, win = "") {{{2
    ; 兼容老版本的vimcore.ahk
    mode(mode, win = "")
    {
        if not IsObject(this.GetWin(win))
            this.SetWin(win, win)
        return this.SetMode(mode, win)
    }

    ; SetMode(modeName, winName) {{{2
    SetMode(modeName, winName = "")
    {
        winObj := This.GetWin(winName)
        return winObj.ChangeMode(modeName)
    }

    ; SetModeFunction(func, modeName, winName = "") {{{2
    SetModeFunction(func, modeName, winName = "")
    {
        winObj := This.GetWin(winName)
        modeObj := winObj.modeList[modeName]
        modeObj.modeFunction := func
    }

    ; GetMode(winName) {{{2
    ; 获取指定win中当前的模式
    GetMode(winName = "")
    {
        winObj := This.GetWin(winName)
        return winObj.modeList[winobj.ExistMode()]
    }

    ; GetInputState {{{2
    GetInputState(WinTitle = "A")
    {
        ControlGet, hwnd, HWND, , , %WinTitle%
        if (A_Cursor = "IBeam")
            return 1
        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
    }

    ; BeforeActionDo(Function, winName = "") {{{2
    BeforeActionDo(Function, winName = "")
    {
        winObj  := this.GetWin(winName)
        winObj.BeforeActionDoFunc := Function
    }

    ; AfterActionDo(Function, winName = "") {{{2
    AfterActionDo(Function, winName = "")
    {
        winObj := this.GetWin(winName)
        winObj.AfterActionDoFunc := Function
    }

    ; SetMaxCount(Int, winName) {{{2
    SetMaxCount(Int, winName = "")
    {
        winObj := This.GetWin(winName)
        winObj.MaxCount := int
    }

    ; GetMaxCount(winName) {{{2
    GetMaxCount(winName = "")
    {
        winObj := This.GetWin(winName)
        return winObj.MaxCount
    }

    ; SetCount(int, winName) {{{2
    SetCount(int, winName = "")
    {
        winObj := This.GetWin(winName)
        winObj.Count := int
    }

    ; GetCount(winName) {{{2
    GetCount(winName = "")
    {
        winObj := This.GetWin(winName)
        return winObj.Count
    }

    ; SetTimeOut(Int, winName) {{{2
    SetTimeOut(Int, winName = "")
    {
        winObj := This.GetWin(winName)
        winObj.TimeOut := int
    }

    ; GetTimeOut(winName) {{{2
    GetTimeOut(winName = "")
    {
        winObj := This.GetWin(winName)
        return winObj.TimeOut
    }

    ; Map(keyName, Action, winName) {{{2
    ; 例 Map("<C-A>jjj", <a>, "TC")
    ; Map("<nowait>jk", <b>, "TC")
    Map(keyName, Action, winName = "")
    {
        if not this.GetAction(Action)
        {
            if Islabel(action)
                this.SetAction(Action, Action)
            else
            {
                MsgBox % "map " keyname " to "  action  " error"
                this.ErrorCode := "MAP_ACTION_ERROR"
                return
            }
        }

        winObj := This.GetWin(winName)
        modeObj := this.GetMode(winName)
        Class := winObj.class
        filepath := winObj.filepath
        if winName
        {
            if strlen(filepath)
                Hotkey, IfWinActive, ahk_exe %filepath%
            else
                Hotkey, IfWinActive, ahk_class %class%
        }
        else
            Hotkey, IfWinActive
        keyName := RegExReplace(keyName, "i)<nowait>", "", nowait)
        keyName := RegExReplace(keyName, "i)<super>", "", super)
        newkeyName := keyName
        index := 0
        Loop
        {
            if not strlen(newkeyName)
                break
            else
            {
                saveMoreKey .= thisKey
                modeobj.SetMoreKey(saveMoreKey)
            }

            if RegExMatch(newkeyName, "P)^<.+?>", m)
            {
                thisKey := SubStr(newkeyName, 1, m)
                newkeyName := SubStr(newkeyName, m+1)
            }
            else
            {
                thisKey := SubStr(newkeyName, 1, 1)
                newKeyName := SubStr(newkeyName, 2)
            }

            if RegExMatch(thisKey, "^([A-Z])$", m)
                thisKey := "<S-" m ">"
            SaveKeyName .= thisKey
            key := this.Convert2AHK(thisKey)
            this.Debug.Add("Map: " thiskey " to: " Action)

            if (Action <> "<Default>")
            {
                Hotkey, %Key%, vim_Key, On, UseErrorLevel
            }
            else
            {
                Hotkey, %Key%, Off, UseErrorLevel
            }

            if ErrorLevel
            {
                Msgbox % KeyName "`n" key "`n映射错误"
                this.ErrorCode := "MAP_KEY_ERROR"
                return
            }
            else
            {
                winObj.SuperKeyList[key] := super
                winObj.KeyList[key] := true
                Index++
            }
        }

        modeObj.SetKeyMap(SavekeyName, Action)
        modeObj.SetNoWait(SavekeyName, nowait)
        return false
    }

    ; ExcludeWin(winName = "", Bold = true) {{{2
    ExcludeWin(winName = "", Bold = true)
    {
        this.ExcludeWinList[winName] := Bold
    }

    ; Toggle(winName) {{{2
    Toggle(winName)
    {
        winObj := this.GetWin(winName)
        winObj.Status := !winObj.Status
        this.Control(winObj.Status, winName)
        return winObj.Status
    }

    ; Control(bold, winName) {{{2
    Control(bold, winName = "", all=false)
    {
        winObj := this.GetWin(winName)
        class := winObj.Class
        filepath := winObj.filepath
        if Strlen(filepath)
            Hotkey, IfWinActive, ahk_exe %filepath%
        else if Strlen(class)
            Hotkey, IfWinActive, ahk_class %class%
        else
            Hotkey, IfWinActive

        this.Debug.Add("===== Control End  =====")
        for i , k in winObj.KeyList
        {
            if winObj.SuperKeyList[i] And (not all)
                Continue
            this.Debug.Add("class: " class "`tkey: " i "`tcontrol: " bold)
            if bold
                Hotkey, %i%, vim_Key, On
            else
                Hotkey, %i%, vim_Key, off
            winObj.KeyList[i] := bold
        }
        this.Debug.Add("===== Control Start =====")
    }

    ; Copy(winName1, winName2) {{{2
    ; 复制winName1到winName2, winName2按class/filepath/title定义
    Copy(winName1, winName2, class, filepath = "", title = "")
    {
        this.debug.Add("Copy>> "winName1 "`t"  winName2 "`t" class)
        w1 := This.GetWin(winName1)
        w2 := this.SetWin(winName2, class, filepath, title)
        w2.class := class
        w2.filepath := filepath
        w2.title := title
        w2.KeyList := w1.KeyList
        w2.SuperKeyList := w1.SuperKeyList
        w2.modeList  := w1.modeList
        w2.mode      := w1.mode
        w2.LastKey   := w1.LastKey
        w2.KeyTemp   := w1.KeyTemp
        w2.MaxCount  := w1.MaxCount
        w2.Count     := w1.Count
        w2.TimeOut   := w1.TimeOut
        w2.Info      := w1.Info
        w2.BeforeActionDoFunc := w1.BeforeActionDoFunc
        w2.AfterActionDoFunc  := w1.AfterActionDoFunc
        w2.ShowInfoFunc := w1.ShowInfoFunc
        w2.HideInfoFunc := w1.HideInfoFunc
        this.Control(Bold := true, winName2, all := true)
        return w2
    }

    ; CopyMode(win, mode, to) {{{2
    ; 在当前的Win中复制一个模式
    CopyMode(winName, fromMode, toMode)
    {
        winObj := This.GetWin(winName)
        winObj.mode := modeName
        winObj.KeyTemp := ""
        winObj.Count := 0
        from := winObj.modeList[fromMode]
        from.name  := toMode
        winObj.modeList[toMode] := from
        return from
    }

    ; Delete(winName) {{{2
    Delete(winName = "") {
        this.Control(false, winName, all := true)
        this.WinList[winName] := ""
    }

    ; GetMore() {{{2
    GetMore(obj = false)
    {
        rt_obj := []
        winObj  := this.GetWin(this.LastFoundWin)
        modeObj := this.GetMode(this.LastFoundWin)
        if Strlen(winObj.KeyTemp)
        {
            r := winObj.KeyTemp "`n"
            rt_obj[1] := {"key":winObj.KeyTemp, "Action":modeObj.GetKeyMap(winObj.KeyTemp)}
            m := "i)^" this.ToMatch(winObj.KeyTemp) ".+"
            for i , k in modeObj.keymapList
            {
                if RegExMatch(i, m)
                {
                    r .= i "`t" modeObj.GetKeyMap(i) "`n"
                    rt_obj[rt_obj.MaxIndex()+1] := {"key":i, "Action":modeObj.GetKeyMap(i)}
                }
            }

            if obj
                return rt_obj
            else
                return r
        }
        else
            if winobj.count
                return winobj.count
    }

    ; Clear() {{{2
    Clear(winName = "") {
        winObj := This.GetWin(winName)
        winObj.KeyTemp := ""
        winObj.Count := 0
    }

    ; Key() {{{2
    Key()
    {
        Global __vimLastAction
        ; 获取winName
        winName := this.CheckWin()
        ; 获取当前的热键
        k := this.CheckCapsLock(this.Convert2VIM(A_ThisHotkey))
        ; 如果winName在排除窗口中，直接发送热键
        if this.ExcludeWinList[winName] {
            Send, % this.Convert2AHK(k, ToSend := true)
            return
        }
        ; 如果当前热键在当前winName无效，判断全局热键中是否有效？
        winObj := this.GetWin(winName)
        if Not winObj.KeyList[A_thisHotkey]
        {
            winObj := this.GetWin()
            if Not winObj.KeyList[A_thisHotkey]
            {
                ; 无效热键，按普通键输出
                Send, % this.Convert2AHK(k, ToSend := true)
                return
            }
            else
                winName := ""
        }

        this.LastFoundWin := winName
        ; 执行在判断热键前的函数, 如果函数返回true，按普通键输出
        if IsFunc(f := winObj.BeforeActionDoFunc)
        {
            if %f%()
            {
                Send, % this.Convert2AHK(k, ToSend := true)
                return
            }
        }

        ; 获取当前模式对应的对象
        modeObj := this.GetMode(winName)
        ; 把当前热键添加到热键缓存中, 并设置最后热键为k
        winObj.KeyTemp .= winObj.LastKey := k
        this.Debug.Add(" win: " winname "`tHotkey: " k)

        /*
            if winObj.Count
                this.Debug.Add(" [" winName "`t热键:" winObj.Count winObj.KeyTemp)
            else
                this.Debug.Add(" [" winName "]`t热键:" winObj.KeyTemp)
        */

        ; 热键缓存是否有对应的Action?
        ; 判断是否有更多热键, 如果当前具有<nowait>设置，则无视更多热键
        if modeObj.GetMoreKey(winObj.KeyTemp) And (Not modeObj.GetNoWait(winObj.KeyTemp))
        {
            ; 启用TimeOut
            if strlen(modeObj.GetKeymap(winObj.KeyTemp))
                if tick := winObj.TimeOut
                    Settimer, Vim_TimeOut, %tick%

            winObj.ShowMore()
            ; 执行在判断热键后的函数, 如果函数返回true，按普通键输出
            if IsFunc(f := winObj.AfterActionDoFunc)
            {
                if %f%()
                    Send, % this.Convert2AHK(k, ToSend := true)
            }

            return
        }

        ; 如果没有更多，热键缓存是否有对应的Action?
        if strlen(actionName := modeObj.GetKeymap(winObj.KeyTemp))
        {
            actObj := this.GetAction(actionName)
            if (actObj.Type = 0) And RegExMatch(actionName , "^<(\d)>$", m)
            {
                ; 数字则进行累加
                winObj.Count := winObj.Count * 10 + m1
                if winObj.MaxCount And winObj.Count > winObj.MaxCount
                    winObj.Count := winObj.MaxCount

                winObj.KeyTemp := ""
                winObj.ShowMore()
                if IsFunc(f := winObj.AfterActionDoFunc)
                    %f%()
                return
            }
            else
            {
                ; 非数字则直接运行
                ;this.Debug.Add("act: " actionName "`tLK: " winObj.KeyTemp)
                __vimLastAction := {"LastKey":k, "winName":winName, "ActionName":ActionName, "KeyTemp":winObj.KeyTemp, "Count":winObj.Count}
                Settimer, Vim_TimeOut, Off
                actObj.Do(winObj.Count)
                winObj.Count := 0
            }
        }
        else
        {
            Settimer, Vim_TimeOut, Off
            ; 如果没有，按普通键输出
            if strlen(actionName := modeObj.GetKeymap(winObj.LastKey))
            {
                actObj := this.GetAction(actionName)
                __vimLastAction := {"LastKey":k, "winName":winName, "ActionName":ActionName, "KeyTemp":winObj.KeyTemp, "Count":winObj.Count}
                actObj.Do(winObj.Count)
                winObj.Count := 0
            }
            else
            {
                Send, % this.Convert2AHK(k, ToSend := true)
                winObj.Count := 0
            }
        }

        winObj.KeyTemp := ""
        winObj.HideMore()
        ; 执行在判断热键后的函数, 如果函数返回true，按普通键输出
        if IsFunc(f := winObj.AfterActionDoFunc)
        {
            if %f%()
                Send, % this.Convert2AHK(k, ToSend := true)
            ; %f%() ;直接运行
        }
        return
    }

    ; IsTimeOut() {{{2
    IsTimeOut()
    {
        winObj  := this.GetWin(this.LastFoundWin)
        modeObj := this.GetMode(this.LastFoundWin)
        act := this.GetAction(modeObj.GetKeyMap(winObj.KeyTemp))
        if act
        {
            winObj.HideMore()
            __vimLastAction := {"LastKey":k, "winName":winName, "ActionName":ActionName, "KeyTemp":winObj.KeyTemp, "Count":winObj.Count}
            act.Do(winObj.Count)
            winObj.Count := 0
            winObj.KeyTemp := ""
            ; 执行在判断热键后的函数, 如果函数返回true，按普通键输出
            if IsFunc(f := winObj.AfterActionDoFunc)
            {
                if %f%()
                Send, % this.Convert2AHK(k, ToSend := true)
            }
            Settimer, Vim_TimeOut, Off
        }
    }

    ; Debug(Bold) {{{2
    Debug(Bold, history = false)
    {
        if Bold
        {
            this.Debug := new __vimDebug(history)
            this.Debug.var(this)
        }
        else
        {
            GUI, vimDebug:Destroy
            this.Debug := ""
        }
    }

    ; Convert2VIM(key) {{{2
    ; 将AHK热键名转换为类VIM的热键名
    ; 例 Convert2VIM("f1")
    Convert2VIM(key)
    {
        if RegExMatch(key, "^[A-Z]$")
            return "<S-" this.Upper(key) ">"
        if RegExMatch(key, "i)^((F1)|(F2)|(F3)|(F4)|(F5)|(F6)|(F7)|(F8)|(F9)|(F10)|(F11)|(F12))$")
            return "<" key ">"
        if RegExMatch(key, "i)^((AppsKey)|(Tab)|(Enter)|(Space)|(Home)|(End)|(CapsLock)|(ScroollLock)|(Up)|(Down)|(Left)|(Right)|(PgUp)|(PgDn))$")
            return "<" key ">"
        if RegExMatch(key, "i)^((BS)|(BackSpace))$")
            return "<BS>"
        if RegExMatch(key, "i)^((Esc)|(Escape))$")
            return "<Esc>"
        if RegExMatch(key, "i)^((Ins)|(Insert))$")
            return "<Insert>"
        if RegExMatch(key, "i)^((Del)|(Delete))$")
            return "<Delete>"
        if RegExMatch(key, "i)^PrintScreen$")
            return "<PrtSc>"
        if RegExMatch(key, "i)^shift\s&\s(.*)", m) or RegExMatch(key, "^\+(.*)", m)
            return "<S-" this.Upper(m1) ">"
        if RegExMatch(key, "i)^lshift\s&\s(.*)", m) or RegExMatch(key, "^<\+(.*)", m)
            return "<LS-" this.Upper(m1) ">"
        if RegExMatch(key, "i)^rshift\s&\s(.*)", m) or RegExMatch(key, "^>\+(.*)", m)
            return "<RS-" this.Upper(m1) ">"
        if RegExMatch(key, "i)^Ctrl\s&\s(.*)", m) or RegExMatch(key, "^\^(.*)", m)
            return "<C-" this.Upper(m1) ">"
        if RegExMatch(key, "i)^lctrl\s&\s(.*)", m) or RegExMatch(key, "^<\^(.*)", m)
            return "<LC-" this.Upper(m1) ">"
        if RegExMatch(key, "i)^rctrl\s&\s(.*)", m) or RegExMatch(key, "^>\^(.*)", m)
            return "<RC-" this.Upper(m1) ">"
        if RegExMatch(key, "i)^alt\s&\s(.*)", m) or RegExMatch(key, "^\!(.*)", m)
            return "<A-" this.Upper(m1) ">"
        if RegExMatch(key, "i)^lalt\s&\s(.*)", m) or RegExMatch(key, "^<\!(.*)", m)
            return "<LA-" this.Upper(m1) ">"
        if RegExMatch(key, "i)^ralt\s&\s(.*)", m) or RegExMatch(key, "^>\!(.*)", m)
            return "<RA-" this.Upper(m1) ">"
        if RegExMatch(key, "i)^lwin\s&\s(.*)", m) or RegExMatch(key, "^#(.*)", m)
            return "<W-" this.Upper(m1) ">"
        if RegExMatch(key, "i)^alt$")
            return "<Alt>"
        if RegExMatch(key, "i)^ctrl$")
            return "<Ctrl>"
        if RegExMatch(key, "i)^shift$")
            return "<Shift>"
        if RegExMatch(key, "i)^lwin$")
            return "<Win>"
        return key
    }

    Upper(k)
    {
        StringUpper, k, k
        return k
    }

    ; Convert2AHK(key, ToSend=false) {{{2
    ; 将类VIM的热键名转换为AHK热键名
    ; 例 Convert2AHK("<F1>")
    Convert2AHK(key, ToSend=false)
    {
        this.CheckCapsLock(key)
        if RegExMatch(key, "^<.*>$")
        {
            key := SubStr(key, 2, strlen(key)-2)
            if RegExMatch(key, "i)^((F1)|(F2)|(F3)|(F4)|(F5)|(F6)|(F7)|(F8)|(F9)|(F10)|(F11)|(F12))$")
                return ToSend ? "{" key "}" : key
            if RegExMatch(key, "i)^((AppsKey)|(Tab)|(Enter)|(Space)|(Home)|(End)|(CapsLock)|(ScroollLock)|(Up)|(Down)|(Left)|(Right)|(PgUp)|(PgDn)|(BS)|(ESC)|(Insert)|(Delete))$")
                return ToSend ? "{" key "}" : key
            if RegExMatch(key, "i)^PrtSc$")
                return ToSend ? "{PrintScreen}" : "PrintScreen"
            if RegExMatch(key, "i)^alt$")
                return ToSend ? "{!}" : "alt"
            if RegExMatch(key, "i)^ctrl$")
                return ToSend ? "{^}" : "ctrl"
            if RegExMatch(key, "i)^shift$")
                return ToSend ? "{+}" : "shift"
            if RegExMatch(key, "i)^win$")
                return ToSend ? "{#}" : "lwin"
            if RegExMatch(key, "<LT>")
                return "<"
            if RegExMatch(key, "<RT>")
                return ">"
            if RegExMatch(key, "i)^S\-(.*)", m)
                return ToSend ? "+" this.CheckToSend(m1) : "+" m1
            if RegExMatch(key, "i)^LS\-(.*)", m)
                return ToSend ? "<+" this.CheckToSend(m1) : "<+" m1
            if RegExMatch(key, "i)^RS-(.*)", m)
                return ToSend ? ">+" this.CheckToSend(m1) : ">+" m1
            if RegExMatch(key, "i)^C\-(.*)", m)
                return ToSend ? "^" this.CheckToSend(m1) : "^" m1
            if RegExMatch(key, "i)^LC\-(.*)", m)
                return ToSend ? "<^" this.CheckToSend(m1) : "<^" m1
            if RegExMatch(key, "i)^RC\-(.*)", m)
                return ToSend ? ">^" this.CheckToSend(m1) : ">^" m1
            if RegExMatch(key, "i)^A\-(.*)", m)
                return ToSend ? "!" this.CheckToSend(m1) : "!" m1
            if RegExMatch(key, "i)^LA\-(.*)", m)
                return ToSend ? "<!" this.CheckToSend(m1) : "<!" m1
            if RegExMatch(key, "i)^RA\-(.*)", m)
                return ToSend ? ">!" this.CheckToSend(m1) : ">!" m1
            if RegExMatch(key, "i)^w\-(.*)", m)
                return ToSend ? "#" this.CheckToSend(m1) : "#" m1
        }
        else
            return key
    }

    CheckToSend(key)
    {
        if RegExMatch(key, "i)^((F1)|(F2)|(F3)|(F4)|(F5)|(F6)|(F7)|(F8)|(F9)|(F10)|(F11)|(F12))$")
            return "{" key "}"
        if RegExMatch(key, "i)^((AppsKey)|(Tab)|(Enter)|(Space)|(Home)|(End)|(CapsLock)|(ScroollLock)|(Up)|(Down)|(Left)|(Right)|(PgUp)|(PgDn)|(BS)|(ESC)|(Insert)|(Delete))$")
            return "{" key "}"
        if RegExMatch(key, "i)^PrtSc$")
            return "{PrintScreen}"
        if RegExMatch(key, "i)^alt$")
            return "{!}"
        if RegExMatch(key, "i)^ctrl$")
            return "{^}"
        if RegExMatch(key, "i)^shift$")
            return "{+}"
        if RegExMatch(key, "i)^win$")
            return "{#}"
        if RegExMatch(key, "<LT>")
            return "<"
        if RegExMatch(key, "<RT>")
            return ">"
        return Key
    }

    ; CheckCapsLock(key) {{{2
    ; 检测CapsLock是否按下，返回对应的值
    ; key 的值为类VIM键，如 CheckCapsLock("<S-A>")
    CheckCapsLock(key)
    {
        if GetKeyState("CapsLock", "T")
        {
            if RegExMatch(key, "^[a-z]$")
                return "<S-" key ">"
            if RegExMatch(key, "i)^<S\-([a-zA-Z])>", m)
            {
                StringLower, key, m1
                return key
            }
        }
        return key
    }

    ToMatch(v)
    {
        v := RegExReplace(v , "\+|\?|\.|\*|\{|\}|\(|\)|\||\^|\$|\[|\]|\\", "\$0")
        return RegExReplace(v , "\s", "\s")
    }
}

; Class __win {{{1
Class __win
{
    __new(class = "", filepath = "", title = "")
    {
        this.class     := class
        this.filepath  := filepath
        this.title     := title
        this.KeyList   := []
        this.SuperKeyList   := []
        this.modeList  := []
        this.Status    := true
        this.mode      := ""
        this.LastKey   := ""
        this.KeyTemp   := ""
        this.MaxCount  := 99
        this.Count     := 0
        this.TimeOut   := 0
        this.Info := default_enable_show_info
        this.BeforeActionDoFunc := ""
        this.AfterActionDoFunc   := ""
        this.ShowInfoFunc := "ShowInfo"
        this.HideInfoFunc := "HideInfo"
    }

    ; ChangeMode(modeName) {{{2
    ; 检查模式是否存在，如存在则返回模式对象，如果不存在则新建并返回模式对象
    ChangeMode(modeName)
    {
        this.mode := modeName
        this.KeyTemp := ""
        this.Count := 0
        if not this.modeList[modeName]
            this.modeList[modeName] := new __Mode(modeName)

        modeObj := this.modeList[modeName]
        if IsFunc(func := modeObj.modeFunction)
            %func%()
        return modeObj
    }

    ; ExistMode() {{{2
    ; 获取当前模式名
    ExistMode()
    {
        return this.mode
    }

    ; SetInfo() {{{2
    SetInfo(bold)
    {
        this.info := bold
    }

    ; SetShowInfo() {{{2
    SetShowInfo(func)
    {
        this.ShowInfoFunc := func
    }

    ; SetHideInfo() {{{2
    SetHideInfo(func)
    {
        this.HideInfoFunc := func
    }

    ; ShowMore() {{{2
    ShowMore()
    {
        if IsFunc(f := this.ShowInfoFunc) And this.Info
            %f%()
    }

    ; HideMore() {{{2
    HideMore()
    {
        if IsFunc(f:=this.HideInfoFunc) And this.Info
            %f%()
    }
}

; Class __Mode {{{1
Class __Mode
{
    __new(modeName)
    {
        this.name  := modeName
        this.keymapList := []
        this.keymoreList := []
        this.nowaitList := []
        this.modeFunction := ""
    }

    ; SetKeyMap(key, action) {{{2
    SetKeyMap(key, action)
    {
        this.keymapList[key] := action
    }

    ; GetKeyMap(key) {{{2
    GetKeyMap(key)
    {
        return this.keymapList[key]
    }

    ; DelKeyMap(key) {{{2
    DelKeyMap(key)
    {
        this.keymapList[key] := ""
    }

    ; SetNoWait(key, bold) {{{2
    ; 无视TimeOut执行热键
    SetNoWait(key, bold)
    {
        this.nowaitList[key] := bold
    }

    ; GetNoWait(key) {{{2
    GetNoWait(key)
    {
        return this.nowaitList[key]
    }

    ; SetMoreKey(key) {{{2
    SetMoreKey(key)
    {
        this.keymoreList[key] := true
    }

    ; GetMoreKey(key) {{{2
    GetMoreKey(key)
    {
        return this.keymoreList[key]
    }
}

; Class __Action {{{1
Class __Action
{
    ; Action 有几种类型
    ; 0 代表执行Action对应的Label (默认)
    ; 1 代表执行Function的值对应的函数
    ; 2 代表运行CmdLine对应的值
    ; 3 代表发送HotString对应的文本

    __new(Name, Comment)
    {
        this.Name := Name
        this.Comment := Comment
        this.MaxTimes := 0
        this.Type := 0
        this.Function := ""
        this.CmdLine := ""
        this.HotString := ""
    }

    ; SetFunction(Function) {{{2
    ; 设置Action执行的函数名
    SetFunction(Function)
    {
        this.Function := Function
        this.Type := 1
    }

    ; SetCmdLine(CmdLine) {{{2
    ; 设置Action运行的字符串
    SetCmdLine(CmdLine)
    {
        this.CmdLine := CmdLine
        this.Type := 2
    }

    ; SetHotString(HotString) {{{2
    ; 设置Action发送的文本
    SetHotString(HotString)
    {
        this.HotString := HotString
        this.Type := 3
    }

    ; SetMaxTimes(Times) {{{2
    ; 设置最大运行次数
    SetMaxTimes(Times)
    {
        this.MaxTimes := Times
    }

    ; Do(Times=1) {{{2
    ; 执行Action
    Do(Times=0)
    {
        Times := !Times ? 1 : Times
        if this.MaxTimes And (Times > this.MaxTimes)
            Times := this.MaxTimes
        Loop, %Times%
        {
            if this.Type = 0
            {
                if IsLabel(l := this.Name)
                    GoSub, %l%
            }
            else if this.Type = 1
            {
                if IsFunc(f := this.Function)
                    %f%()
            }
            else if this.Type = 2
            {
                c := this.CmdLine
                Run, %cmd%
            }
            else if This.Type = 3
            {
                t := this.HotString
                Send, %t%
            }
        }
    }
}

; Class __Plugin {{{1
Class __Plugin
{
    __new(PluginName)
    {
        this.PluginName := PluginName
        this.Author := ""
        this.Ver := ""
        this.Comment := ""
    }

    ; CheckSub() {{{2
    CheckSub()
    {
        if IsLabel(p := this.PluginName)
        {
            GoSub, %p%
            this.Error := false
        }
        else
            this.Error := true
    }
}

; Class __vimDebug {{{1
Class __vimDebug
{
    __new(key)
    {
        this.mode := key
        if key
        {
            GUI, vimDebug:Destroy
            GUI, vimDebug:+hwnd_vimdebug -Caption +ToolWindow +Border
            GUI, vimDebug:color, 454545, 454545
            GUI, vimDebug:font, s16 cFFFFFF
            GUI, vimDebug:Add, Edit, x-2 y-2 w400 h60 readonly
            GUI, vimDebug:Show, w378 h56 y600
            WinSet, AlwaysOnTop, On, ahk_id %_vimdebug%
        }
        else
        {
            GUI, vimDebug:font, s12
            GUI, vimDebug:Destroy
            GUI, vimDebug:Add, Edit, x10 y10 w400 h300 readonly
            GUI, vimDebug:Add, Edit, x10 y320 w400 h26 readonly
            GUI, vimDebug:Show, w420 h356
        }
    }

    var(obj)
    {
        this.vim := obj
    }

    Set(v)
    {
        winName := this.vim.CheckWin()
        winObj := this.vim.GetWin(winName)
        if winObj.Count
            k := " 热键缓存:" winObj.Count winObj.KeyTemp
        else
             k := " 热键缓存:" winObj.KeyTemp
        GUI, vimDebug:Default
        GUIControl, , Edit1, %v%
        GUIControl, , Edit2, %k%
    }

    Get()
    {
        GUI, vimDebug:Default
        GUIControlGet, v, , Edit1
        return v
    }

    ; Add(v) {{{2
    Add(v)
    {
        b := this.Get()
        if this.mode
            this.Set(b)
        else
            this.Set(v "`n" b)
    }

    ; Clear() {{{2
    Clear()
    {
        this.Set("")
    }
}

; 初始化class_Vim

vim_Init:
    #UseHook
    SetKeyDelay, -1
return

; 用于热键映射
vim_Key:
    vim.Key()
return

; 用于热键超时
vim_TimeOut:
    vim.IsTimeOut()
return

; 用于Count计数
Internal:
    __v.SetPlugin("Internal", "Array", "0.1", "内置插件")
    __v.SetAction("<1>", "数字 1")
    __v.SetAction("<2>", "数字 2")
    __v.SetAction("<3>", "数字 3")
    __v.SetAction("<4>", "数字 4")
    __v.SetAction("<5>", "数字 5")
    __v.SetAction("<6>", "数字 6")
    __v.SetAction("<7>", "数字 7")
    __v.SetAction("<8>", "数字 8")
    __v.SetAction("<9>", "数字 9")
    __v.SetAction("<0>", "数字 0")
    __v.SetAction("<>", "空操作")
    __v.SetAction("<Pass>", "空操作")
    __v.SetAction("<Default>", "恢复默认")
    __v := ""
return

<1>:
<2>:
<3>:
<4>:
<5>:
<6>:
<7>:
<8>:
<9>:
<0>:
<>:
<Pass>:
<Default>:
return

Class_vim()
{
    global __v
    GoSub, Vim_Init
    __v := v := new __vim
    __v.LoadPlugin("Internal")
    return v
}

GetLastAction()
{
    global __vimLastAction
    return __vimLastAction
}

ShowInfo()
{
    Global vim
    obj := vim.GetMore(true)
    winObj := vim.GetWin(vim.LastFoundWin)
    if winObj.Count
        np .= winObj.Count
    Loop, % obj.MaxIndex()
    {
        act := vim.GetAction(obj[A_Index]["Action"])

        ; Type = 1 : Function
        if (act.Type = 1)
        {
            ActionDescList := act.Comment
            Key := obj[A_Index]["key"]
            np .= Key "`t" %ActionDescList%[Key] "`n"
        }
        else
        {
            np .= obj[A_Index]["key"] "`t" act.Comment "`n"
        }

        If (A_Index = 1)
            np .= "=====================`n"
    }
    MouseGetPos, posx, posy, A
    posx += 40
    posy += 40
    Tooltip, %np%, %posx%, %posy%
}

HideInfo()
{
    ; 当屏幕有非快捷键补全帮助信息时，不清理
    Global showToolTipStatus
    if (!showToolTipStatus)
    {
        Tooltip
    }
}

; 定义数据结构
; Class __vim {{{1
Class __vim
{
    __new()
    {
        this.PluginList := []
        this.WinList    := []
        this.WinInfo    := []
        this.ActionList := []
        this.ActionFromPlugin := []
        this.ExcludeWinList :=[]
        this.winGlobal  := new __win
        this.ErrorCode  := 0
        tihs.ActionFromPluginName := ""
        this.LastFoundWin := ""
    }

    ; LoadPlugin(PluginName) {{{2
    ; 用于注册插件
    LoadPlugin(PluginName)
    {
        If this.PluginList[PluginName]
            return this.PluginList[PluginName]
        p := new __Plugin(PluginName)
        this.PluginList[PluginName] := p
        back := this.ActionFromPluginName
        this.ActionFromPluginName := PluginName
        p.CheckSub()
        If p.Error
        {
            msgbox load plugin "%PluginName%" error
            this.ActionFromPluginName := back
        }
    }

    ; SetPlugin(PluginName, Author="", Ver="", Comment="") {{{2
    ; 设置Plugin信息
    SetPlugin(PluginName, Author="", Ver="", Comment="")
    {
        p := this.PluginList[PluginName]
        p.Author := Author
        p.Ver := Ver
        p.Comment := Comment
    }

    ; GetPlugin(PluginName) {{{2
    ; 获取Plugin信息
    GetPlugin(PluginName)
    {
        return this.PluginList[PluginName]
    }

    ; Comment(action, desc, complex=1) {{{2
    ; 兼容老版本的vimcore.ahk
    Comment(action, desc="", complex=1)
    {
        act := this.SetAction(Action, Desc)
        If not complex ; 不允许多次运行
            act.SetMaxTimes(1)
      return act
    }

    ; SetAction(Name, Comment) {{{2
    ; 用于为Action(动作)进行注释
    SetAction(Name, Comment="")
    {
        If this.ActionList[Name]
            ra := This.ActionList[Name]
        Else
            ra := This.ActionList[Name] := new __Action(Name, Comment)
        This.ActionFromPlugin[Name] := this.ActionFromPluginName
        return ra
    }

    ; GetAction(Name) {{{2
    ; 获取Action的信息
    GetAction(Name)
    {
        return this.ActionList[Name]
    }

    ; SetWin(winName, class, filepath, title) {{{2
    ; 添加win成员
    SetWin(winName, class, filepath="", title="")
    {
        If this.WinList[winName]
            rw := this.WinList[winName]
        Else
            rw := this.WinList[winName] := new __win(class, filepath, title)
        this.WinInfo["class`t"class]       := winName
        this.WinInfo["filepath`t"filepath] := winName
        this.WinInfo["title`t"title]       := winName
        return rw
    }

    ; GetWin(winName) {{{2
    GetWin(winName="")
    {
        If strlen(winName)
            return this.WinList[winName]
        Else
            return this.winGlobal
    }

    ; CheckWin() {{{2
    CheckWin()
    {
        /*
        WinGetTitle, t, A
        If Strlen(winName:=this.WinInfo["title`t"t])
            return winName
        */

        WinGet, f, ProcessName, A
        If Strlen(winName:=this.WinInfo["filepath`t"f])
            return winName
        WinGetClass, c, A
        If Strlen(winName:=this.WinInfo["class`t"c])
            return winName
    }

    ; mode(mode, win="") {{{2
    ; 兼容老版本的vimcore.ahk
    mode(mode, win="")
    {
        If not IsObject(this.GetWin(win))
            this.SetWin(win, win)
        return this.SetMode(mode, win)
    }

    ; SetMode(modeName, winName) {{{2
    SetMode(modeName, winName="")
    {
        winObj := This.GetWin(winName)
        return winObj.ChangeMode(modeName)
    }

    ; SetModeFunction(func, modeName, winName="") {{{2
    SetModeFunction(func, modeName, winName="")
    {
        winObj := This.GetWin(winName)
        modeObj := winObj.modeList[modeName]
        modeObj.modeFunction := func
    }

    ; GetMode(winName) {{{2
    ; 获取指定win中当前的模式
    GetMode(winName="")
    {
        winObj := This.GetWin(winName)
        return winObj.modeList[winobj.ExistMode()]
    }

    ; GetInputState {{{2
    GetInputState(WinTitle="A")
    {
        ControlGet, hwnd, HWND, , , %WinTitle%
        if (A_Cursor = "IBeam")
            return 1
        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
    }

    ; BeforeActionDo(Function, winName="") {{{2
    BeforeActionDo(Function, winName="")
    {
        winObj  := this.GetWin(winName)
        winObj.BeforeActionDoFunc := Function
    }

    ; AfterActionDo(Function, winName="") {{{2
    AfterActionDo(Function, winName="")
    {
        winObj := this.GetWin(winName)
        winObj.AfterActionDoFunc := Function
    }

    ; SetMaxCount(Int, winName) {{{2
    SetMaxCount(Int, winName="")
    {
        winObj := This.GetWin(winName)
        winObj.MaxCount := int
    }

    ; GetMaxCount(winName) {{{2
    GetMaxCount(winName="")
    {
        winObj := This.GetWin(winName)
        return winObj.MaxCount
    }

    ; SetCount(int, winName) {{{2
    SetCount(int, winName="")
    {
        winObj := This.GetWin(winName)
        winObj.Count := int
    }

    ; GetCount(winName) {{{2
    GetCount(winName="")
    {
        winObj := This.GetWin(winName)
        return winObj.Count
    }

    ; SetTimeOut(Int, winName) {{{2
    SetTimeOut(Int, winName="")
    {
        winObj := This.GetWin(winName)
        winObj.TimeOut := int
    }

    ; GetTimeOut(winName) {{{2
    GetTimeOut(winName="")
    {
        winObj := This.GetWin(winName)
        return winObj.TimeOut
    }

    ; Map(keyName, Action, winName) {{{2
    ; 例 Map("<C-A>jjj", <a>, "TC")
    ; Map("<nowait>jk", <b>, "TC")
    Map(keyName, Action, winName="")
    {
        If not this.GetAction(Action)
        {
            If Islabel(action)
                this.SetAction(Action, Action)
            Else
            {
                msgbox % "map " keyname " to "  action  " error"
                this.ErrorCode := "MAP_ACTION_ERROR"
                return
            }
        }

        winObj := This.GetWin(winName)
        modeObj := this.GetMode(winName)
        Class:=winObj.class
        filepath := winObj.filepath
        If winName
        {
            If strlen(filepath)
                Hotkey, IfWinActive, ahk_exe %filepath%
            Else
                Hotkey, IfWinActive, ahk_class %class%
        }
        Else
            Hotkey, IfWinActive
        keyName := RegExReplace(keyName, "i)<nowait>", "", nowait)
        keyName := RegExReplace(keyName, "i)<super>", "", super)
        newkeyName := keyName
        index := 0
        Loop
        {
            If not strlen(newkeyName)
                break
            Else
            {
                saveMoreKey .= thisKey
                modeobj.SetMoreKey(saveMoreKey)
            }

            If RegExMatch(newkeyName, "P)^<.+?>", m)
            {
                thisKey := SubStr(newkeyName, 1, m)
                newkeyName := SubStr(newkeyName, m+1)
            }
            Else
            {
                thisKey := SubStr(newkeyName, 1, 1)
                newKeyName := SubStr(newkeyName, 2)
            }

            If RegExMatch(thisKey, "^([A-Z])$", m)
                thisKey := "<S-" m ">"
            SaveKeyName .= thisKey
            key := this.Convert2AHK(thisKey)
            this.Debug.Add("Map: " thiskey " to: " Action)

            If (Action <> "<Default>")
            {
                Hotkey, %Key%, vim_Key, On, UseErrorLevel
            }
            Else
            {
                Hotkey, %Key%, Off, UseErrorLevel
            }

            If ErrorLevel
            {
                Msgbox % KeyName "`n" key "`n映射错误"
                this.ErrorCode := "MAP_KEY_ERROR"
                return
            }
            Else
            {
                winObj.SuperKeyList[key] := super
                winObj.KeyList[key] := True
                Index++
            }
        }

        modeObj.SetKeyMap(SavekeyName, Action)
        modeObj.SetNoWait(SavekeyName, nowait)
        return False
    }

    ; ExcludeWin(winName="", Bold=True) {{{2
    ExcludeWin(winName="", Bold=True)
    {
        this.ExcludeWinList[winName] := Bold
    }

    ; Toggle(winName) {{{2
    Toggle(winName)
    {
        winObj := this.GetWin(winName)
        winObj.Status := !winObj.Status
        this.Control(winObj.Status, winName)
        return winObj.Status
    }

    ; Control(bold, winName) {{{2
    Control(bold, winName="", all=false)
    {
        winObj := this.GetWin(winName)
        class := winObj.Class
        filepath := winObj.filepath
        If Strlen(filepath)
            Hotkey, IfWinActive, ahk_exe %filepath%
        Else If Strlen(class)
            Hotkey, IfWinActive, ahk_class %class%
        Else
            Hotkey, IfWinActive

        this.Debug.Add("===== Control End  =====")
        for i , k in winObj.KeyList
        {
            If winObj.SuperKeyList[i] And ( not all )
                Continue
            this.Debug.Add("class: " class "`tkey: " i "`tcontrol: " bold )
            If bold
                Hotkey, %i%, vim_Key, On
            Else
                Hotkey, %i%, vim_Key, off
            winObj.KeyList[i] := bold
        }
        this.Debug.Add("===== Control Start =====")
    }

    ; Copy(winName1, winName2) {{{2
    ; 复制winName1到winName2, winName2按class/filepath/title定义
    Copy(winName1, winName2, class, filepath="", title="")
    {
        this.debug.Add("Copy>> "winName1 "`t"  winName2 "`t" class)
        w1 := This.GetWin(winName1)
        w2 := this.SetWin(winName2, class, filepath, title)
        w2.class := class
        w2.filepath := filepath
        w2.title := title
        w2.KeyList := w1.KeyList
        w2.SuperKeyList := w1.SuperKeyList
        w2.modeList  := w1.modeList
        w2.mode      := w1.mode
        w2.LastKey   := w1.LastKey
        w2.KeyTemp   := w1.KeyTemp
        w2.MaxCount  := w1.MaxCount
        w2.Count     := w1.Count
        w2.TimeOut   := w1.TimeOut
        w2.Info      := w1.Info
        w2.BeforeActionDoFunc := w1.BeforeActionDoFunc
        w2.AfterActionDoFunc  := w1.AfterActionDoFunc
        w2.ShowInfoFunc := w1.ShowInfoFunc
        w2.HideInfoFunc := w1.HideInfoFunc
        this.Control(Bold:=True, winName2, all:=true)
        return w2
    }

    ; CopyMode(win, mode, to) {{{2
    ; 在当前的Win中复制一个模式
    CopyMode(winName, fromMode, toMode)
    {
        winObj := This.GetWin(winName)
        winObj.mode := modeName
        winObj.KeyTemp := ""
        winObj.Count := 0
        from := winObj.modeList[fromMode]
        from.name  := toMode
        winObj.modeList[toMode] := from
        return from
    }

    ; Delete(winName) {{{2
    Delete(winName="") {
        this.Control(False, winName, all:=True)
        this.WinList[winName] := ""
    }

    ; GetMore() {{{2
    GetMore(obj = false)
    {
        rt_obj := []
        winObj  := this.GetWin(this.LastFoundWin)
        modeObj := this.GetMode(this.LastFoundWin)
        If Strlen(winObj.KeyTemp)
        {
            r := winObj.KeyTemp "`n"
            rt_obj[1] := {"key":winObj.KeyTemp, "Action":modeObj.GetKeyMap(winObj.KeyTemp)}
            m := "i)^" this.ToMatch(winObj.KeyTemp) ".+"
            for i , k in modeObj.keymapList
            {
                If RegExMatch(i, m)
                {
                    r .= i "`t" modeObj.GetKeyMap(i) "`n"
                    rt_obj[rt_obj.MaxIndex()+1] := {"key":i, "Action":modeObj.GetKeyMap(i)}
                }
            }

            if obj
                return rt_obj
            else
                return r
        }
        Else
            If winobj.count
                return winobj.count
    }

    ; Clear() {{{2
    Clear(winName="") {
        winObj := This.GetWin(winName)
        winObj.KeyTemp := ""
        winObj.Count := 0
    }

    ; Key() {{{2
    Key()
    {
        Global __vimLastAction
        ; 获取winName
        winName := this.CheckWin()
        ; 获取当前的热键
        k := this.CheckCapsLock(this.Convert2VIM(A_ThisHotkey))
        ; 如果winName在排除窗口中，直接发送热键
        If this.ExcludeWinList[winName] {
            Send, % this.Convert2AHK(k, ToSend:=True)
            return
        }
        ; 如果当前热键在当前winName无效，判断全局热键中是否有效？
        winObj := this.GetWin(winName)
        If Not winObj.KeyList[A_thisHotkey]
        {
            winObj := this.GetWin()
            If Not winObj.KeyList[A_thisHotkey]
            {
                ; 无效热键，按普通键输出
                Send, % this.Convert2AHK(k, ToSend:=True)
                return
            }
            Else
                winName := ""
        }

        this.LastFoundWin := winName
        ; 执行在判断热键前的函数, 如果函数返回True，按普通键输出
        If IsFunc(f:=winObj.BeforeActionDoFunc){
            If %f%(){
                Send, % this.Convert2AHK(k, ToSend:=True)
                return
            }
        }

        ; 获取当前模式对应的对象
        modeObj := this.GetMode(winName)
        ; 把当前热键添加到热键缓存中, 并设置最后热键为k
        winObj.KeyTemp .= winObj.LastKey := k
        this.Debug.Add(" win: " winname "`tHotkey: " k)

        /*
            If winObj.Count
                this.Debug.Add(" [" winName "`t热键:" winObj.Count winObj.KeyTemp  )
            Else
                this.Debug.Add(" [" winName "]`t热键:" winObj.KeyTemp  )
        */

        ; 热键缓存是否有对应的Action?
        ; 判断是否有更多热键, 如果当前具有<nowait>设置，则无视更多热键
        If modeObj.GetMoreKey(winObj.KeyTemp) And (Not modeObj.GetNoWait(winObj.KeyTemp))
        {
            ; 启用TimeOut
            If strlen(modeObj.GetKeymap(winObj.KeyTemp))
                If tick := winObj.TimeOut
                    Settimer, Vim_TimeOut, %tick%

            winObj.ShowMore()
            ; 执行在判断热键后的函数, 如果函数返回True，按普通键输出
            If IsFunc(f:=winObj.AfterActionDoFunc){
                If %f%()
                    Send, % this.Convert2AHK(k, ToSend:=True)
            }

            return
        }

        ; 如果没有更多，热键缓存是否有对应的Action?
        If strlen(actionName := modeObj.GetKeymap(winObj.KeyTemp))
        {
            actObj := this.GetAction(actionName)
            If ( actObj.Type = 0 ) And RegExMatch(actionName , "^<(\d)>$", m)
            {
                ; 数字则进行累加
                winObj.Count := winObj.Count * 10 + m1
                If winObj.MaxCount And winObj.Count > winObj.MaxCount
                    winObj.Count := winObj.MaxCount

                winObj.KeyTemp := ""
                winObj.ShowMore()
                If IsFunc(f:=winObj.AfterActionDoFunc)
                    %f%()
                return
            }
            Else
            {
                ; 非数字则直接运行
                ;this.Debug.Add("act: " actionName "`tLK: " winObj.KeyTemp)
                __vimLastAction := {"LastKey":k, "winName":winName, "ActionName":ActionName, "KeyTemp":winObj.KeyTemp, "Count":winObj.Count}
                Settimer, Vim_TimeOut, Off
                actObj.Do(winObj.Count)
                winObj.Count := 0
            }
        }
        Else
        {
            Settimer, Vim_TimeOut, Off
            ; 如果没有，按普通键输出
            If strlen(actionName := modeObj.GetKeymap(winObj.LastKey))
            {
                actObj := this.GetAction(actionName)
                __vimLastAction := {"LastKey":k, "winName":winName, "ActionName":ActionName, "KeyTemp":winObj.KeyTemp, "Count":winObj.Count}
                actObj.Do(winObj.Count)
                winObj.Count := 0
            }
            Else
            {
                Send, % this.Convert2AHK(k, ToSend:=True)
                winObj.Count := 0
            }
        }

        winObj.KeyTemp := ""
        winObj.HideMore()
        ; 执行在判断热键后的函数, 如果函数返回True，按普通键输出
        If IsFunc(f:=winObj.AfterActionDoFunc)
        {
            If %f%()
                Send, % this.Convert2AHK(k, ToSend:=True)
            ; %f%() ;直接运行
        }
        return
    }

    ; IsTimeOut() {{{2
    IsTimeOut()
    {
        winObj  := this.GetWin(this.LastFoundWin)
        modeObj := this.GetMode(this.LastFoundWin)
        act := this.GetAction(modeObj.GetKeyMap(winObj.KeyTemp))
        If act
        {
            winObj.HideMore()
            __vimLastAction := {"LastKey":k, "winName":winName, "ActionName":ActionName, "KeyTemp":winObj.KeyTemp, "Count":winObj.Count}
            act.Do(winObj.Count)
            winObj.Count := 0
            winObj.KeyTemp := ""
            ; 执行在判断热键后的函数, 如果函数返回True，按普通键输出
            If IsFunc(f:=winObj.AfterActionDoFunc)
            {
                If %f%()
                Send, % this.Convert2AHK(k, ToSend:=True)
            }
            Settimer, Vim_TimeOut, Off
        }
    }

    ; Debug(Bold) {{{2
    Debug(Bold, history=false)
    {
        If Bold
        {
            this.Debug := new __vimDebug(history)
            this.Debug.var(this)
        }
        Else
        {
            GUI, vimDebug:Destroy
            this.Debug := ""
        }
    }
; TODO Code style
        ; Convert2VIM(key) {{{2
        ; 将AHK热键名转换为类VIM的热键名
        ; 例 Convert2VIM("f1")
        Convert2VIM(key)
        {
            If RegExMatch(key, "^[A-Z]$")
                return "<S-" this.Upper(key) ">"
            If RegExMatch(key, "i)^((F1)|(F2)|(F3)|(F4)|(F5)|(F6)|(F7)|(F8)|(F9)|(F10)|(F11)|(F12))$")
                return "<" key ">"
            If RegExMatch(key, "i)^((AppsKey)|(Tab)|(Enter)|(Space)|(Home)|(End)|(CapsLock)|(ScroollLock)|(Up)|(Down)|(Left)|(Right)|(PgUp)|(PgDn))$")
                return "<" key ">"
            If RegExMatch(key, "i)^((BS)|(BackSpace))$")
                return "<BS>"
            If RegExMatch(key, "i)^((Esc)|(Escape))$")
                return "<Esc>"
            If RegExMatch(key, "i)^((Ins)|(Insert))$")
                return "<Insert>"
            If RegExMatch(key, "i)^((Del)|(Delete))$")
                return "<Delete>"
            If RegExMatch(key, "i)^PrintScreen$")
                return "<PrtSc>"
            If RegExMatch(key, "i)^shift\s&\s(.*)", m) or RegExMatch(key, "^\+(.*)", m)
                return "<S-" this.Upper(m1) ">"
            If RegExMatch(key, "i)^lshift\s&\s(.*)", m) or RegExMatch(key, "^<\+(.*)", m)
                return "<LS-" this.Upper(m1) ">"
            If RegExMatch(key, "i)^rshift\s&\s(.*)", m) or RegExMatch(key, "^>\+(.*)", m)
                return "<RS-" this.Upper(m1) ">"
            If RegExMatch(key, "i)^Ctrl\s&\s(.*)", m) or RegExMatch(key, "^\^(.*)", m)
                return "<C-" this.Upper(m1) ">"
            If RegExMatch(key, "i)^lctrl\s&\s(.*)", m) or RegExMatch(key, "^<\^(.*)", m)
                return "<LC-" this.Upper(m1) ">"
            If RegExMatch(key, "i)^rctrl\s&\s(.*)", m) or RegExMatch(key, "^>\^(.*)", m)
                return "<RC-" this.Upper(m1) ">"
            If RegExMatch(key, "i)^alt\s&\s(.*)", m) or RegExMatch(key, "^\!(.*)", m)
                return "<A-" this.Upper(m1) ">"
            If RegExMatch(key, "i)^lalt\s&\s(.*)", m) or RegExMatch(key, "^<\!(.*)", m)
                return "<LA-" this.Upper(m1) ">"
            If RegExMatch(key, "i)^ralt\s&\s(.*)", m) or RegExMatch(key, "^>\!(.*)", m)
                return "<RA-" this.Upper(m1) ">"
            If RegExMatch(key, "i)^lwin\s&\s(.*)", m) or RegExMatch(key, "^#(.*)", m)
                return "<W-" this.Upper(m1) ">"
            If RegExMatch(key, "i)^alt$")
                return "<Alt>"
            If RegExMatch(key, "i)^ctrl$")
                return "<Ctrl>"
            If RegExMatch(key, "i)^shift$")
                return "<Shift>"
            If RegExMatch(key, "i)^lwin$")
                return "<Win>"
            ;If RegExMatch(key, "i)^esc\s&\s(.*)", m)
            ;    return "<E-" this.Upper(m1) ">"
            return key
        }
        Upper(k)
        {
            StringUpper, k, k
            return k
        }
        ; Convert2AHK(key, ToSend=False) {{{2
        ; 将类VIM的热键名转换为AHK热键名
        ; 例 Convert2AHK("<F1>")
        Convert2AHK(key, ToSend=False)
        {
          this.CheckCapsLock(key)
            If RegExMatch(key, "^<.*>$")
            {
                key := SubStr(key, 2, strlen(key)-2)
                If RegExMatch(key, "i)^((F1)|(F2)|(F3)|(F4)|(F5)|(F6)|(F7)|(F8)|(F9)|(F10)|(F11)|(F12))$")
                    return ToSend ? "{" key "}" : key
                If RegExMatch(key, "i)^((AppsKey)|(Tab)|(Enter)|(Space)|(Home)|(End)|(CapsLock)|(ScroollLock)|(Up)|(Down)|(Left)|(Right)|(PgUp)|(PgDn)|(BS)|(ESC)|(Insert)|(Delete))$")
                    return ToSend ? "{" key "}" : key
                If RegExMatch(key, "i)^PrtSc$")
                    return ToSend ? "{PrintScreen}" : "PrintScreen"
                If RegExMatch(key, "i)^alt$")
                    return ToSend ? "{!}" : "alt"
                If RegExMatch(key, "i)^ctrl$")
                    return ToSend ? "{^}" : "ctrl"
                If RegExMatch(key, "i)^shift$")
                    return ToSend ? "{+}" : "shift"
                If RegExMatch(key, "i)^win$")
                    return ToSend ? "{#}" : "lwin"
                If RegExMatch(key, "<LT>")
                    return "<"
                If RegExMatch(key, "<RT>")
                    return ">"
                If RegExMatch(key, "i)^S\-(.*)", m)
                    return ToSend ? "+" this.CheckToSend(m1) : "+" m1
                If RegExMatch(key, "i)^LS\-(.*)", m)
                    return ToSend ? "<+" this.CheckToSend(m1) : "<+" m1
                If RegExMatch(key, "i)^RS-(.*)", m)
                    return ToSend ? ">+" this.CheckToSend(m1) : ">+" m1
                If RegExMatch(key, "i)^C\-(.*)", m)
                    return ToSend ? "^" this.CheckToSend(m1) : "^" m1
                If RegExMatch(key, "i)^LC\-(.*)", m)
                    return ToSend ? "<^" this.CheckToSend(m1) : "<^" m1
                If RegExMatch(key, "i)^RC\-(.*)", m)
                    return ToSend ? ">^" this.CheckToSend(m1) : ">^" m1
                If RegExMatch(key, "i)^A\-(.*)", m)
                    return ToSend ? "!" this.CheckToSend(m1) : "!" m1
                If RegExMatch(key, "i)^LA\-(.*)", m)
                    return ToSend ? "<!" this.CheckToSend(m1) : "<!" m1
                If RegExMatch(key, "i)^RA\-(.*)", m)
                    return ToSend ? ">!" this.CheckToSend(m1) : ">!" m1
                If RegExMatch(key, "i)^w\-(.*)", m)
                    return ToSend ? "#" this.CheckToSend(m1) : "#" m1
                ;If RegExMatch(key, "i)^e\-(.*)", m)
                ;    return ToSend ? "{esc}" this.CheckToSend(m1) : "esc & " m1
            }
            Else
                    return key
        }
        CheckToSend(key)
        {
            If RegExMatch(key, "i)^((F1)|(F2)|(F3)|(F4)|(F5)|(F6)|(F7)|(F8)|(F9)|(F10)|(F11)|(F12))$")
                return "{" key "}"
            If RegExMatch(key, "i)^((AppsKey)|(Tab)|(Enter)|(Space)|(Home)|(End)|(CapsLock)|(ScroollLock)|(Up)|(Down)|(Left)|(Right)|(PgUp)|(PgDn)|(BS)|(ESC)|(Insert)|(Delete))$")
                return "{" key "}"
            If RegExMatch(key, "i)^PrtSc$")
                return "{PrintScreen}"
            If RegExMatch(key, "i)^alt$")
                return "{!}"
            If RegExMatch(key, "i)^ctrl$")
                return "{^}"
            If RegExMatch(key, "i)^shift$")
                return "{+}"
            If RegExMatch(key, "i)^win$")
                return "{#}"
            If RegExMatch(key, "<LT>")
                return "<"
            If RegExMatch(key, "<RT>")
                return ">"
      Return Key
        }
        ; CheckCapsLock(key) {{{2
        ; 检测CapsLock是否按下，返回对应的值
        ; key 的值为类VIM键，如 CheckCapsLock("<S-A>")
        CheckCapsLock(key)
        {
            If GetKeyState("CapsLock", "T")
            {
                If RegExMatch(key, "^[a-z]$")
                    return "<S-" key ">"
                If RegExMatch(key, "i)^<S\-([a-zA-Z])>", m)
        {
          StringLower, key, m1
                    return key
        }
            }
            return key
        }
        ToMatch(v)
        {
            v := RegExReplace(v , "\+|\?|\.|\*|\{|\}|\(|\)|\||\^|\$|\[|\]|\\", "\$0")
           Return RegExReplace(v , "\s", "\s")
        }
}
; Class __win {{{1
Class __win
{
    __new(class="", filepath="", title=""){
        this.class     := class
        this.filepath  := filepath
        this.title     := title
        this.KeyList   := []
        this.SuperKeyList   := []
        this.modeList  := []
        this.Status    := True
        this.mode      := ""
        this.LastKey   := ""
        this.KeyTemp   := ""
        this.MaxCount  := 99
        this.Count     := 0
        this.TimeOut   := 0
        this.Info := default_enable_show_info
        this.BeforeActionDoFunc := ""
        this.AfterActionDoFunc   := ""
        this.ShowInfoFunc := "ShowInfo"
        this.HideInfoFunc := "HideInfo"
    }
    ; ChangeMode(modeName) {{{2
    ; 检查模式是否存在，如存在则返回模式对象，如果不存在则新建并返回模式对象
    ChangeMode(modeName)
    {
        this.mode := modeName
        this.KeyTemp := ""
        this.Count := 0
        If not this.modeList[modeName]
            this.modeList[modeName] := new __Mode(modeName)
    modeObj := this.modeList[modeName]
    If IsFunc(func := modeObj.modeFunction)
      %func%()
        return modeObj
    }
  ; ExistMode() {{{2
    ; 获取当前模式名
    ExistMode()
    {
        return this.mode
    }
    ; SetInfo() {{{2
    SetInfo(bold)
    {
        this.info := bold
    }
    ; SetShowInfo() {{{2
    SetShowInfo(func)
    {
        this.ShowInfoFunc := func
    }
    ; SetHideInfo() {{{2
    SetHideInfo(func)
    {
        this.HideInfoFunc := func
    }
    ; ShowMore() {{{2
    ShowMore()
    {
        If IsFunc(f:=this.ShowInfoFunc) And this.Info
            %f%()
    }
    ; HideMore() {{{2
    HideMore()
    {
        If IsFunc(f:=this.HideInfoFunc) And this.Info
            %f%()
    }
}

; Class __Mode {{{1
Class __Mode
{
    __new(modeName)
    {
        this.name  := modeName
        this.keymapList := []
        this.keymoreList := []
        this.nowaitList := []
        this.modeFunction := ""
    }
    ; SetKeyMap(key, action) {{{2
    SetKeyMap(key, action)
    {
        this.keymapList[key] := action
    }
    ; GetKeyMap(key) {{{2
    GetKeyMap(key)
    {
        return this.keymapList[key]
    }
    ; DelKeyMap(key) {{{2
    DelKeyMap(key)
    {
        this.keymapList[key] := ""
    }
    ; SetNoWait(key, bold) {{{2
    ; 无视TimeOut执行热键
    SetNoWait(key, bold)
    {
        this.nowaitList[key] := bold
    }
    ; GetNoWait(key) {{{2
    GetNoWait(key)
    {
        return this.nowaitList[key]
    }
    ; SetMoreKey(key) {{{2
    SetMoreKey(key)
    {
        this.keymoreList[key] := true
    }
    ; GetMoreKey(key) {{{2
    GetMoreKey(key)
    {
        return this.keymoreList[key]
    }
}
; Class __Action {{{1
Class __Action
{
        ; Action 有几种类型
        ; 0 代表执行Action对应的Label (默认)
        ; 1 代表执行Function的值对应的函数
        ; 2 代表运行CmdLine对应的值
        ; 3 代表发送HotString对应的文本

    __new(Name, Comment){
        this.Name := Name
        this.Comment := Comment
        this.MaxTimes := 0
        this.Type := 0
    this.Function := ""
    this.CmdLine := ""
    this.HotString := ""
    }
    ; SetFunction(Function) {{{2
    ; 设置Action执行的函数名
    SetFunction(Function)
    {
        this.Function := Function
        this.Type := 1
    }
    ; SetCmdLine(CmdLine) {{{2
    ; 设置Action运行的字符串
    SetCmdLine(CmdLine)
    {
        this.CmdLine := CmdLine
        this.Type := 2
    }
    ; SetHotString(HotString) {{{2
    ; 设置Action发送的文本
    SetHotString(HotString)
    {
        this.HotString := HotString
        this.Type := 3
    }
    ; SetMaxTimes(Times) {{{2
    ; 设置最大运行次数
    SetMaxTimes(Times)
    {
        this.MaxTimes := Times
    }
    ; Do(Times=1) {{{2
    ; 执行Action
    Do(Times=0)
    {
        Times := !Times ? 1 : Times
        If this.MaxTimes And ( Times > this.MaxTimes)
                Times := this.MaxTimes
        Loop, %Times%
        {
            If this.Type = 0
            {
                If IsLabel(l:=this.Name)
                    GoSub, %l%
            }
            If this.Type = 1
            {
                If IsFunc(f:=this.Function)
                    %f%()
            }
            If this.Type = 2
            {
                c := this.CmdLine
                Run, %cmd%
            }
            If This.Type = 3
            {
                t := this.HotString
                Send, %t%
            }
        }
    }
}

; Class __Plugin {{{1
Class __Plugin
{
    __new(PluginName)
    {
            this.PluginName := PluginName
            this.Author := ""
            this.Ver := ""
            this.Comment := ""
    }
    ; CheckSub() {{{2
    CheckSub()
    {
            If IsLabel(p:=this.PluginName)
            {
                GoSub, %p%
                this.Error := False
            }
            Else
                this.Error := True
    }
}
; Class __vimDebug {{{1
Class __vimDebug
{
    __new(key)
    {
    this.mode := key
    If key
    {
        GUI, vimDebug:Destroy
        GUI, vimDebug:+hwnd_vimdebug  -Caption +ToolWindow +Border
        GUI, vimDebug:color, 454545, 454545
        GUI, vimDebug:font, s16 cFFFFFF
        GUI, vimDebug:Add, Edit, x-2 y-2 w400 h60 readonly
        GUI, vimDebug:Show, w378 h56 y600
    WinSet, AlwaysOnTop, On, ahk_id %_vimdebug%
    }
    Else
    {
          GUI, vimDebug:font, s12
          GUI, vimDebug:Destroy
          GUI, vimDebug:Add, Edit, x10 y10 w400 h300 readonly
          GUI, vimDebug:Add, Edit, x10 y320 w400 h26 readonly
          GUI, vimDebug:Show, w420 h356
    }
    }
  var(obj)
  {
    this.vim := obj
  }
    Set(v)
    {
    winName := this.vim.CheckWin()
    winObj := this.vim.GetWin(winName)
    If winObj.Count
             k := " 热键缓存:" winObj.Count winObj.KeyTemp
    Else
             k := " 热键缓存:" winObj.KeyTemp
        GUI, vimDebug:Default
        GUIControl, , Edit1, %v%
        GUIControl, , Edit2, %k%
    }
    Get()
    {
        GUI, vimDebug:Default
        GUIControlGet, v, , Edit1
        return v
    }
    ; Add(v) {{{2
    Add(v)
    {
        b:=this.Get()
    If this.mode
          this.Set(b)
    else
          this.Set(v "`n" b)
    }
    ; Clear() {{{2
    Clear()
    {
        this.Set("")
    }
}


Add ` key for symbol correction of Persian keyboard. Also, change the language when it is pressed (temporarily).

#InstallKeybdHook
#SingleInstance Force
SetTitleMatchMode, RegEx

; ahk_class PotPlayer

#SC01F::Send {Media_Play_Pause}

$+1::Send {!}
$+2::Send {@}
$+3::Send {#}
$+4::Send {$}
$+5::Send {`%}
$+6::Send {^}
;$+7::Send {&}
$+8::Send {*}

GetKeyboardLayout()
{
	HKL := DllCall("GetKeyboardLayout", "UInt", 0, "Ptr")
	Return HKL
}

GetKeyboardLayoutName()
{
	VarSetCapacity(Str, 1000)
	DllCall("GetKeyboardLayoutName", "Str", Str, "Int")
	Return Str
}

ActivateKeyboardLayout(HKL) ; This does not work.
{
	; For initialization, necessary to run only once.
	DllCall("Ole32.dll\OleInitialize", "Ptr", 0, "Int")
	DllCall("LoadKeyboardLayout", "Str", "00020409", "Int")

	T := DllCall("ActivateKeyboardLayout", "UInt", HKL, "UInt", 0x00000000, "PTR")
	If (!T)
	{
		MsgBox, Error
	}
}

$`::
	Send {``}
	If (Lang = 0)
	{
		PostMessage, 0x50, 0, 0xF0020409,, A
		Lang := 1
	}
	Else
	{
		PostMessage, 0x50, 0, 0xF03A0429,, A
		Lang := 0
	}
	Return

Capslock::
	SetCapsLockState, Off
	If (Lang = 0)
	{
		PostMessage, 0x50, 0, 0xF0020409,, A
		Lang := 1
	}
	Else
	{
		PostMessage, 0x50, 0, 0xF03A0429,, A
		Lang := 0
	}
	Return

<^Capslock::
	SetCapsLockState, Off
	PostMessage, 0x50, 0, 0xF01A0409,, A
	Return

>^Capslock::
	SetCapsLockState, Off
	PostMessage, 0x50, 0, 0xF01B0409,, A
	Return

!Capslock::
	T := GetKeyboardLayout()
	H := Format("{1:X}", T)
	MsgBox, %T% %H%
	Return

Temp()
{
	;^1:: ; This line is commented out.
		T := GetKeyboardLayout()
		H := Format("{1:X}", T)
		MsgBox, %T% %H%
		Return

	;^2:: ; This line is commented out.
		;ActivateKeyboardLayout(0xF0020409)
		PostMessage, 0x50, 0, 0xF0020409,, A
		MsgBox, Done.
		Return
}

#IfWinActive, ^Git Gui ahk_class ^TkTopLevel$

^+t::
	Send !c
	Send {Down 3}
	Send {Enter}
	Return
^+i::
	Send !c
	Send {Down 4}
	Send {Enter}
#IfWinActive, ahk_class ^#32770$
	Send y
#IfWinActive, ^Git Gui ahk_class ^TkTopLevel$
	Return
^+u::
	Send !c
	Send {Down 5}
	Send {Enter}
	Return
^+j::
	Send !c
	Send {Down 6}
	Send {Enter}
	Return

#IfWinActive

#InstallKeybdHook
#SingleInstance Force
SetTitleMatchMode, RegEx

; ahk_class PotPlayer

#SC01F::Send {Media_Play_Pause}

$+1::Send {!}
$+2::Send {@}
$+3::Send {#}
$+4::Send {$}
$+5::Send {`%}
$+6::Send {^}
;$+7::Send {&}
$+8::Send {*}

GetKeyboardLayout()
{
	HKL := DllCall("GetKeyboardLayout", "UInt", 0, "Ptr")
	Return HKL
}

GetKeyboardLayoutName()
{
	VarSetCapacity(Str, 1000)
	DllCall("GetKeyboardLayoutName", "Str", Str, "Int")
	Return Str
}

ActivateKeyboardLayout(HKL) ; This does not work.
{
	; For initialization, necessary to run only once.
	DllCall("Ole32.dll\OleInitialize", "Ptr", 0, "Int")
	DllCall("LoadKeyboardLayout", "Str", "00020409", "Int")

	T := DllCall("ActivateKeyboardLayout", "UInt", HKL, "UInt", 0x00000000, "PTR")
	If (!T)
	{
		MsgBox, Error
	}
}

Capslock::
	SetCapsLockState, Off
	If (Lang = 0)
	{
		PostMessage, 0x50, 0, 0xF0020409,, A
		Lang := 1
	}
	Else
	{
		PostMessage, 0x50, 0, 0xF03A0429,, A
		Lang := 0
	}
	Return

<^Capslock::
	SetCapsLockState, Off
	PostMessage, 0x50, 0, 0xF01A0409,, A
	Return

>^Capslock::
	SetCapsLockState, Off
	PostMessage, 0x50, 0, 0xF01B0409,, A
	Return

!Capslock::
	T := GetKeyboardLayout()
	H := Format("{1:X}", T)
	MsgBox, %T% %H%
	Return

Temp()
{
	;^1:: ; This line is commented out.
		T := GetKeyboardLayout()
		H := Format("{1:X}", T)
		MsgBox, %T% %H%
		Return

	;^2:: ; This line is commented out.
		;ActivateKeyboardLayout(0xF0020409)
		PostMessage, 0x50, 0, 0xF0020409,, A
		MsgBox, Done.
		Return
}

#IfWinActive, ^Git Gui ahk_class ^TkTopLevel$

^+t::
	Send !c
	Send {Down 3}
	Send {Enter}
	Return
^+i::
	Send !c
	Send {Down 4}
	Send {Enter}
#IfWinActive, ahk_class ^#32770$
	Send y
#IfWinActive, ^Git Gui ahk_class ^TkTopLevel$
	Return
^+u::
	Send !c
	Send {Down 5}
	Send {Enter}
	Return
^+j::
	Send !c
	Send {Down 6}
	Send {Enter}
	Return

#IfWinActive


Updated Autohotkey for PC98

Updated Autohotkey for PC98

RunWait %1% %2% %3% %4% %5% %6% %7% %8% %9%
ExitApp

LAlt::Send {vk1D}
RAlt::Send {vk1C}
LCtrl & RAlt::Send ^{vk1C}
RCtrl::LAlt
LWin & LAlt::Send {vkF2}
Ctrl & Space::ControlSend WinExist("A"),^{Space}

; Muhenkan (PC98 NFER key)
; Henkan (PC98 XFER key)
;Muhenkan / 無変換 -> {vk1D}
;Henkan / 変換　-> {vk1C}
;Kana / かな -> {vkF2}
;IME ON/OF -> {vkF3}, {vkF4}

RunWait %1% %2% %3% %4% %5% %6% %7% %8% %9%
ExitApp

LAlt::Send {vk1D}
RAlt::Send {vk1C}
LCtrl & RAlt::Send ^{vk1C}
RCtrl::LAlt
LWin & LAlt::Send {vkF2}

; Muhenkan (PC98 NFER key)
; Henkan (PC98 XFER key)
;Muhenkan / 無変換 -> {vk1D}
;Henkan / 変換　-> {vk1C}
;Kana / かな -> {vkF2}
;IME ON/OF -> {vkF3}, {vkF4}


Вычистка

Вычистка

actionShowMethodsList() {
	Global

	RunWait, system\OneScript\bin\woscript.exe scripts\\.os
	if (ErrorLevel = 0) {
		return
	}

	nStr := ErrorLevel
	SendInput ^%KeyG%
	WinWait,
	SendInput, %nStr%{ENTER}

	SendInput, {home}
	SendInput, ^{NumpadAdd}
}

actionShowRegionsList() {
	Global

	RunWait, system\OneScript\bin\woscript.exe scripts\\.os ,,Hide
	if (ErrorLevel = 0) {
		return
	}

	nStr := ErrorLevel
	SendInput, ^%KeyG%
	WinWait,
	SendInput, %nStr%{ENTER}

	SendInput, {home}
	SendInput, ^{NumpadAdd}
}

actionShowExtFilesList() {
	Global

	; RunWait, wscript scripts\ExtFiles.js
	RunWait, system\OneScript\bin\woscript.exe scripts\ExtFiles.os,,

	NewText := getTextFromFile()
	If (NewText <> "") {
		ClipWait
		Sleep 1
		set_locale_ru()
		SendInput, !%KeyA%
		SendInput, {DOWN}{DOWN}{Enter}
		WinWait,
		SendInput, ^%KeyV%{Enter}
	}
}

actionShowScriptManager() {
	RunWait, system\OneScript\bin\woscript.exe scripts\.os,,
}

actionShowPrevWords() {
	RunWait, system\OneScript\bin\woscript.exe scripts\\.os allwords,,
	pasteTextFromFile()
}

actionGotoMethodBegin() {
	Global

	getTextUp()
	RunWait, system\OneScript\bin\woscript.exe scripts\\.os ,,Hide
	if (ErrorLevel > 0) {
		nStr := ErrorLevel
		SendInput, {CtrlDown}%KeyG%{CtrlUp}
		WinWait,
		SendInput,%nStr%{ENTER}
	}
	SendInput, {home}
}

actionGotoMethodEnd() {
	Global

	getTextUp()
	RunWait, system\OneScript\bin\woscript.exe scripts\\.os ,,Hide
	if (ErrorLevel > 0) {
		nStr := ErrorLevel
		SendInput ^%KeyG%
		WinWait,
		SendInput %nStr%{ENTER}
		SendInput ^{SC01A}
	}
	SendInput, {home}
}

actionShowRegExSearch() {
	Global

	RunWait, system\OneScript\bin\woscript.exe scripts\\.os RegExSearch,,Hide
	if (ErrorLevel > 0) {
		nStr := ErrorLevel
		Sleep 1
		SendInput ^%KeyG%
		WinWait,
		SendInput %nStr%{ENTER}
	}
	SendInput, {home}
}

actionShowRegExSearchLastResult() {
	Global

	SendInput, {home}
	RunWait, system\OneScript\bin\woscript.exe scripts\\.os ,,Hide
	if (ErrorLevel > 0) {
		nStr := ErrorLevel
		SendInput ^%KeyG%
		WinWait,
		SendInput %nStr%{ENTER}
	}
	SendInput, {home}
}

actionShowLastSelect() {
	Global

	SendInput, {home}
	; RunWait, wscript scripts.js null last
	RunWait, system\OneScript\bin\woscript.exe scripts\\.os ,,Hide
	if (ErrorLevel > 0) {
		nStr := ErrorLevel
		SendInput ^%KeyG%
		WinWait,
		SendInput %nStr%{ENTER}
	}
	SendInput, {home}
	SendInput, ^{NumpadAdd}
}

actionRunAuthorComments(data) {
	RunWait, system\OneScript\bin\oscript.exe scripts\.os %data%,,hide
}

actionShowPreprocMethod() {
	RunWait, system\OneScript\bin\woscript.exe scripts\.os ,,
}

actionShowSimpleMetaSearch() {
	Global

	SendInput, ^+%KeyC%
	Sleep 10
	SendInput ^%KeyF%
}

actionShowIncomingObjectTypes() {
	Global
try {
	SendInput, %KeyContextMenu%
	SendInput, {UP}{UP}{UP}{ENTER}
	Sleep 100
	SendInput, {Enter}
	; Sleep 1
	SendInput, ^!%KeyO%
	ActivateWindowByTitle(" ")
	SendInput, ^%KeyA%
	; ClipWait
	Sleep 1
	putTextFromResultWindowInFile(0)
	module = tmp\module.txt

	RunWait, wscript scripts\scripts.js %module% gototype
	;RunWait, system\OneScript\bin\oscript.exe scripts\\.os
		; MsgBox %ErrorLevel%
		Sleep 1
	if (ErrorLevel > 0) {
		SendInput, ^{END}
		UpCount := ErrorLevel
		Loop %UpCount%
		{
			SendInput, {UP}
		}
		SendInput, {ENTER}
	}
	SendInput, {HOME}

	}  Catch, er {
		MsgBox, er
    Reload
}
}

actionShowMetadataNavigator() {
	Global

	module = tmp\module.txt

	; clear old data
	FileDelete %module%
	FileAppend,, %module%
	RunWait, system\inputbox.exe %module%

	NewText := getTextFromFile()
	If (NewText <> "") {
		; go to service msgs
		SendInput, ^!%KeyO%
		SendInput, ^+%KeyC%
		ActivateWindowByTitle(" ")
		Sleep 1
		;
		ControlGetFocus, WinType

		If (WinType <> "V8Grid1") {
			;     -    ,  .
			SendInput, {Tab}
		}

		; show search dlg
		SendInput, ^%KeyF%
		WinWait,
		pasteTextFromFile()
		SendInput, {Enter}

		Sleep 2000

		ActivateWindowByTitle(" ")

		SendInput, ^%KeyA%
		ClipWait
		SendInput, {Left}{Enter}
		putTextFromResultWindowInFile(0)
		NewText := getTextFromFile()
		If (NewText <> "") {
			SendInput, ^{END}
			RunWait, wscript scripts\scripts.js %module% gotoobject
			NewText := getTextFromFile()
			If (NewText <> "") {
				SendInput, {Home}
				SendInput, ^%KeyF%
				SendInput +{ins}

				SendInput, !{Insert}
				ClipWait
				SendInput, {Enter}
				SendInput, {Enter}
			}
		}
	}
}

showMenu() {
	createMenuItems()
	Menu, Popup, Show
}

actionRun1Script() {
	module = tmp\module.os

	SendInput ^{SC01E}^{ins}{Left}
	ClipWait

	FileDelete %module%

	FileAppend, %Clipboard%, %module%, UTF-8
	RunWait, cmd "/K system\OneScript\bin\oscript.exe tmp/module.os"

}

actionGoToPrevContainedWord() {

	clipboard =

	SendInput ^+{left}^{ins}{right}
	RunWait, system\OneScript\bin\woscript.exe scripts\.os prev,,
}

actionGoToNextContainedWord() {

	clipboard =

	SendInput ^+{right}^{ins}{left}
	RunWait, system\OneScript\bin\woscript.exe scripts\.os next,,
}

actionShowMethodName() {
	Global

	getTextUp()
	RunWait, system\OneScript\bin\woscript.exe scripts\\.os ,,

}

actionOneStyleSelection() {
    ;    1, ..
    global
    SendInput, !+%KeyF%
	RunWait, system\OneScript\bin\oscript.exe scripts\OneStyle\Main.os,,Hide
}

actionWindowsManager() {
	detect_hidden = 0
	WinGet controls, ControlListHwnd
	static WINDOW_TEXT_SIZE := 32767 ; Defined in AutoHotkey source.
	VarSetCapacity(buf, WINDOW_TEXT_SIZE * (A_IsUnicode ? 2 : 1))
	text := ""
	Loop Parse, controls, `n
	{
		if !detect_hidden && !DllCall("IsWindowVisible", "ptr", A_LoopField)
			continue
		if !DllCall("GetWindowText", "ptr", A_LoopField, "str", buf, "int", WINDOW_TEXT_SIZE)
			continue
		if (buf = "") {
			continue
		}
		text .= buf "`r`n"
	}

	module = tmp\module.txt
	FileDelete %module%
	FileAppend, %text%, %module%, UTF-8

	RunWait, system\SelectValueSharp.exe %module%
	FileRead, text, tmp\module.txt
	Loop Parse, controls, `n
	{
		if !DllCall("GetWindowText", "ptr", A_LoopField, "str", buf, "int", WINDOW_TEXT_SIZE)
			continue
		 if (buf = text) {
		 	WinActivate, ahk_id %A_LoopField%
		 }
	}
}

actionResultSearchFilter() {

	;
	ActivateWindowByTitle(" ")

	clipboard =
	;
	SendInput, ^%KeyA%^{ins}
	;SendInput, ^{ins}
	ClipWait
	SendInput, {home}

	module = tmp\module.txt
	FileDelete %module%
	FileAppend, %Clipboard%, %module%, UTF-8

	SendInput, {home}
	RunWait, system\OneScript\bin\woscript.exe scripts\\.os ,,Hide
	if (ErrorLevel > 0) {
		UpCount := ErrorLevel
		ActivateWindowByTitle(" ")
		Loop %UpCount%
		{
			SendInput, {down}
		}
		SendInput, {ENTER}
	}

}

actionContinueRow() {
	SendInput, {SHIFTDOWN}{up}{up}{up}{SHIFTUP}^{Insert}
	ClipWait
	SendInput, {Right}
	RunWait, system\OneScript\bin\woscript.exe scripts\.os
}

actionShowMethodsList() {
	Global

	RunWait, system\OneScript\bin\woscript.exe scripts\\.os
	if (ErrorLevel = 0) {
		return
	}

	nStr := ErrorLevel
	SendInput ^%KeyG%
	WinWait,
	SendInput, %nStr%{ENTER}

	SendInput, {home}
	SendInput, ^{NumpadAdd}
}

actionShowRegionsList() {
	Global

	RunWait, system\OneScript\bin\woscript.exe scripts\\.os ,,Hide
	if (ErrorLevel = 0) {
		return
	}

	nStr := ErrorLevel
	SendInput, ^%KeyG%
	WinWait,
	SendInput, %nStr%{ENTER}

	SendInput, {home}
	SendInput, ^{NumpadAdd}
}

actionShowExtFilesList() {
	Global

	; RunWait, wscript scripts\ExtFiles.js
	RunWait, system\OneScript\bin\woscript.exe scripts\ExtFiles.os,,

	NewText := getTextFromFile()
	If (NewText <> "") {
		ClipWait
		Sleep 1
		set_locale_ru()
		SendInput, !%KeyA%
		SendInput, {DOWN}{DOWN}{Enter}
		WinWait,
		SendInput, ^%KeyV%{Enter}
	}
}

actionShowScriptManager() {
	RunWait, system\OneScript\bin\woscript.exe scripts\.os,,
}

actionShowPrevWords() {
	RunWait, system\OneScript\bin\woscript.exe scripts\\.os allwords,,
	pasteTextFromFile()
}

actionGotoMethodBegin() {
	Global

	getTextUp()
	RunWait, system\OneScript\bin\woscript.exe scripts\\.os ,,Hide
	if (ErrorLevel > 0) {
		nStr := ErrorLevel
		SendInput, {CtrlDown}%KeyG%{CtrlUp}
		WinWait,
		SendInput,%nStr%{ENTER}
	}
	SendInput, {home}
}

actionGotoMethodEnd() {
	Global

	getTextUp()
	RunWait, system\OneScript\bin\woscript.exe scripts\\.os ,,Hide
	if (ErrorLevel > 0) {
		nStr := ErrorLevel
		SendInput ^%KeyG%
		WinWait,
		SendInput %nStr%{ENTER}
		SendInput ^{SC01A}
	}
	SendInput, {home}
}

actionShowRegExSearch() {
	Global

	RunWait, system\OneScript\bin\woscript.exe scripts\\.os RegExSearch,,Hide
	if (ErrorLevel > 0) {
		nStr := ErrorLevel
		Sleep 1
		SendInput ^%KeyG%
		WinWait,
		SendInput %nStr%{ENTER}
	}
	SendInput, {home}
}

actionShowRegExSearchLastResult() {
	Global

	SendInput, {home}
	RunWait, system\OneScript\bin\woscript.exe scripts\\.os ,,Hide
	if (ErrorLevel > 0) {
		nStr := ErrorLevel
		SendInput ^%KeyG%
		WinWait,
		SendInput %nStr%{ENTER}
	}
	SendInput, {home}
}

actionShowLastSelect() {
	Global

	SendInput, {home}
	; RunWait, wscript scripts.js null last
	RunWait, system\OneScript\bin\woscript.exe scripts\\.os ,,Hide
	if (ErrorLevel > 0) {
		nStr := ErrorLevel
		SendInput ^%KeyG%
		WinWait,
		SendInput %nStr%{ENTER}
	}
	SendInput, {home}
	SendInput, ^{NumpadAdd}
}

actionRunAuthorComments(data) {
	RunWait, system\OneScript\bin\oscript.exe scripts\.os %data%,,hide
}

actionRunLinksToItems() {
	putSelectionInFile()
	RunWait, wscript scripts\generator.js null simple-managment
	pasteTextFromFile()
}

actionShowCodeGenerator() {
	RunWait, wscript scripts\generator.js null generator
	pasteTextFromFile()
}

actionShowPreprocMethod() {
	RunWait, system\OneScript\bin\woscript.exe scripts\.os ,,
}

actionShowSimpleMetaSearch() {
	Global

	SendInput, ^+%KeyC%
	Sleep 10
	SendInput ^%KeyF%
}

actionShowIncomingObjectTypes() {
	Global
try {
	SendInput, %KeyContextMenu%
	SendInput, {UP}{UP}{UP}{ENTER}
	Sleep 100
	SendInput, {Enter}
	; Sleep 1
	SendInput, ^!%KeyO%
	ActivateWindowByTitle(" ")
	SendInput, ^%KeyA%
	; ClipWait
	Sleep 1
	putTextFromResultWindowInFile(0)
	module = tmp\module.txt

	RunWait, wscript scripts\scripts.js %module% gototype
	;RunWait, system\OneScript\bin\oscript.exe scripts\\.os
		; MsgBox %ErrorLevel%
		Sleep 1
	if (ErrorLevel > 0) {
		SendInput, ^{END}
		UpCount := ErrorLevel
		Loop %UpCount%
		{
			SendInput, {UP}
		}
		SendInput, {ENTER}
	}
	SendInput, {HOME}

	}  Catch, er {
		MsgBox, er
    Reload
}
}

actionShowMetadataNavigator() {
	Global

	module = tmp\module.txt

	; clear old data
	FileDelete %module%
	FileAppend,, %module%
	RunWait, system\inputbox.exe %module%

	NewText := getTextFromFile()
	If (NewText <> "") {
		; go to service msgs
		SendInput, ^!%KeyO%
		SendInput, ^+%KeyC%
		ActivateWindowByTitle(" ")
		Sleep 1
		;
		ControlGetFocus, WinType

		If (WinType <> "V8Grid1") {
			;     -    ,  .
			SendInput, {Tab}
		}

		; show search dlg
		SendInput, ^%KeyF%
		WinWait,
		pasteTextFromFile()
		SendInput, {Enter}

		Sleep 2000

		ActivateWindowByTitle(" ")

		SendInput, ^%KeyA%
		ClipWait
		SendInput, {Left}{Enter}
		putTextFromResultWindowInFile(0)
		NewText := getTextFromFile()
		If (NewText <> "") {
			SendInput, ^{END}
			RunWait, wscript scripts\scripts.js %module% gotoobject
			NewText := getTextFromFile()
			If (NewText <> "") {
				SendInput, {Home}
				SendInput, ^%KeyF%
				SendInput +{ins}

				SendInput, !{Insert}
				ClipWait
				SendInput, {Enter}
				SendInput, {Enter}
			}
		}
	}
}

showMenu() {
	createMenuItems()
	Menu, Popup, Show
}

actionRun1Script() {
	module = tmp\module.os

	SendInput ^{SC01E}^{ins}{Left}
	ClipWait

	FileDelete %module%

	FileAppend, %Clipboard%, %module%, UTF-8
	RunWait, cmd "/K system\OneScript\bin\oscript.exe tmp/module.os"

}

actionGoToPrevContainedWord() {

	clipboard =

	SendInput ^+{left}^{ins}{right}
	RunWait, system\OneScript\bin\woscript.exe scripts\.os prev,,
}

actionGoToNextContainedWord() {

	clipboard =

	SendInput ^+{right}^{ins}{left}
	RunWait, system\OneScript\bin\woscript.exe scripts\.os next,,
}

actionShowMethodName() {
	Global

	getTextUp()
	RunWait, system\OneScript\bin\woscript.exe scripts\\.os ,,

}

actionGenerateServerMethodFromCurMethod() {
	Global

	getTextUp()
	RunWait, system\OneScript\bin\oscript.exe scripts\\.os ,,Hide

}

actionOneStyleSelection() {
    ;    1, ..
    global
    SendInput, !+%KeyF%
	RunWait, system\OneScript\bin\oscript.exe scripts\OneStyle\Main.os,,Hide
}

actionWindowsManager() {
	detect_hidden = 0
	WinGet controls, ControlListHwnd
	static WINDOW_TEXT_SIZE := 32767 ; Defined in AutoHotkey source.
	VarSetCapacity(buf, WINDOW_TEXT_SIZE * (A_IsUnicode ? 2 : 1))
	text := ""
	Loop Parse, controls, `n
	{
		if !detect_hidden && !DllCall("IsWindowVisible", "ptr", A_LoopField)
			continue
		if !DllCall("GetWindowText", "ptr", A_LoopField, "str", buf, "int", WINDOW_TEXT_SIZE)
			continue
		if (buf = "") {
			continue
		}
		text .= buf "`r`n"
	}

	module = tmp\module.txt
	FileDelete %module%
	FileAppend, %text%, %module%, UTF-8

	RunWait, system\SelectValueSharp.exe %module%
	FileRead, text, tmp\module.txt
	Loop Parse, controls, `n
	{
		if !DllCall("GetWindowText", "ptr", A_LoopField, "str", buf, "int", WINDOW_TEXT_SIZE)
			continue
		 if (buf = text) {
		 	WinActivate, ahk_id %A_LoopField%
		 }
	}
}

actionResultSearchFilter() {

	;
	ActivateWindowByTitle(" ")

	clipboard =
	;
	SendInput, ^%KeyA%^{ins}
	;SendInput, ^{ins}
	ClipWait
	SendInput, {home}

	module = tmp\module.txt
	FileDelete %module%
	FileAppend, %Clipboard%, %module%, UTF-8

	SendInput, {home}
	RunWait, system\OneScript\bin\woscript.exe scripts\\.os ,,Hide
	if (ErrorLevel > 0) {
		UpCount := ErrorLevel
		ActivateWindowByTitle(" ")
		Loop %UpCount%
		{
			SendInput, {down}
		}
		SendInput, {ENTER}
	}

}

actionContinueRow() {
	SendInput, {SHIFTDOWN}{up}{up}{up}{SHIFTUP}^{Insert}
	ClipWait
	SendInput, {Right}
	RunWait, system\OneScript\bin\woscript.exe scripts\.os
}

actionTextWinExt() {
	; MsgBox go
	RunWait, system\OneScript\bin\woscript.exe scripts\WinExtTest.os,,
}


remove old remote logins

remove old remote logins

#NoEnv
#Persistent
if FileExist("C:/Users/Chris") != ""
{
    Home = 1
    WordProcessor = C:\Program Files (x86)\LibreOffice 4\program\swriter.exe
    Spreadsheet = C:\Program Files (x86)\LibreOffice 4\program\scalc.exe
    VisualStudio = C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\devenv.exe
    VisualStudioProjects = Explorer C:\Users\chris\Documents\Visual Studio 2012\Projects
    GoogleEarth = C:\Program Files (x86)\Google\Google Earth\client\googleearth.exe
}
if FileExist("C:/Users/IBM_ADMIN") != ""
{
    Work = 1
    WordProcessor = C:\Program Files (x86)\OpenOffice 4\program\swriter.exe
    Spreadsheet = C:\Program Files (x86)\OpenOffice 4\program\scalc.exe
    GoogleEarth = C:\Program Files (x86)\Google\Google Earth Pro\client\googleearth.exe
}
Return

^Capslock::Capslock
Capslock::LCtrl

!#a::Run "C:\Program Files (x86)\Vim\vim74\gvim.exe" %A_MyDocuments%/AutoHotkey.ahk
^#a::Run AutoHotkey

;#a::Run
#c::Run Chrome
#g::Run %GoogleEarth%
#h::Run C:\cygwin64\bin\mintty.exe -w max -i /Cygwin-Terminal.ico -
#+h::Run %A_MyDocuments%/../Program Files/Cygwin-setup-x86_64.exe
#j::RemoteLogin1()
#n::Run Notepad
#o::StartOctave()
#q::Run Explorer %A_MyDocuments%\stuff
#s::Run acrord32
#v::Run C:\Program Files (x86)\JetBrains\PyCharm Community Edition 4.5.1\bin\pycharm.exe
#w::Run %WordProcessor%
#x::Run %Spreadsheet%
#y::Run powershell
#^y::Run cmd
#+y::Run "C:\Program Files (x86)\Vim\vim74\gvim.exe" C:\Users\Chris\Documents\WindowsPowerShell\profile.ps1
#z::Run Firefox
#]::WinMinimize A

+Space::_

; Unused Keys Win+Key combinations
;#Escape
;#k
;#`
;#,
;#i
;#.
;#;
;#/
;#[
;#'
;#]
;#\
;#Backspace
;#Enter
#Insert::ClipText()
;#Delete
;#Home
;#End
;#PageDown
;#PageUp

; Don't use these key combinations
;#e opens explorer
;#d shows desktop
;#r opens run dialog
;#f opens windows search
;#t focuses task bar
;#b focuses notification area
;#u opens ease of use control panel
;#m opens start menu along with program
;#l locks workstation when regular windows key is used
;#p opens some kind of screen management menu
;win + top row numberkeys, selects programs from the task bar
;#- windows magnifier zoom out
;#= windows magnifier zoom in
;#Space
;win + arrow keys, manipulates windows

#Numpad0::PlaceActiveWindow(0, 0, 1, 1)

#Numpad1::PlacePattern1()
PlacePattern1()
{
    global LastPattern
    global Spot
    if (LastPattern != 1)
        Spot := -1
    LastPattern := 1
    Spot := mod(Spot + 1, 2)
    if (Spot == 0)
        PlaceActiveWindow(0, 0, 1, 1/2)
    if (Spot == 1)
        PlaceActiveWindow(0, 1/2, 1, 1/2)
}

#Numpad2::PlacePattern2()
PlacePattern2()
{
    global LastPattern
    global Spot
    if (LastPattern != 2)
        Spot := -1
    LastPattern := 2
    Spot := mod(Spot + 1, 2)
    if (Spot == 0)
        PlaceActiveWindow(0, 0, 1/2, 1)
    if (Spot == 1)
        PlaceActiveWindow(1/2, 0, 1/2, 1)
}

#Numpad3::PlacePattern3()
PlacePattern3()
{
    global LastPattern
    global Spot
    if (LastPattern != 3)
        Spot := -1
    LastPattern := 3
    Spot := mod(Spot + 1, 4)
    if (Spot == 0)
        PlaceActiveWindow(0, 0, 1/2, 1/2)
    if (Spot == 1)
        PlaceActiveWindow(1/2, 0, 1/2, 1/2)
    if (Spot == 2)
        PlaceActiveWindow(0, 1/2, 1/2, 1/2)
    if (Spot == 3)
        PlaceActiveWindow(1/2, 1/2, 1/2, 1/2)
}

#Numpad4::PlacePattern4()
PlacePattern4()
{
    global LastPattern
    global Spot
    if (LastPattern != 4)
        Spot := -1
    LastPattern := 4
    Spot := mod(Spot + 1, 2)
    if (Spot == 0)
        PlaceActiveWindow(0, 0, 1, 2/3)
    if (Spot == 1)
        PlaceActiveWindow(0, 2/3, 1, 1/3)
}

#Numpad5::PlacePattern5()
PlacePattern5()
{
    global LastPattern
    global Spot
    if (LastPattern != 5)
        Spot := -1
    LastPattern := 5
    Spot := mod(Spot + 1, 2)
    if (Spot == 0)
        PlaceActiveWindow(0, 0, 1, 3/4)
    if (Spot == 1)
        PlaceActiveWindow(0, 3/4, 1, 1/4)
}

#`::ToggleWindowBorder()
#\::ToggleWindowBorder()
ToggleWindowBorder()
{
    SetWinDelay 10
    WinGet state, MinMax, A
    if (state == 1)
        PlaceActiveWindow(0, 0, 1, 1)
    WinSet Style, ^0x840000, A
    WinGetPos X, Y, Width, Height, A
    WinMove A, , X, Y, Width, Height + 1
    WinMove A, , X, Y, Width, Height
}

;#^f::ToggleFocusFollow()
;FocusFollow = 0
;ToggleFocusFollow()
;{
;    global FocusFollow
;    FocusFollow := !FocusFollow
;    SetFocusFollow(FocusFollow)
;}
;SetFocusFollow(enabled)
;{
;    SPI_SETACTIVEWINDOWTRACKING = 0x1001
;    SPIF_UPDATEINIFILE = 1
;    SPIF_SENDCHANGE = 2
;    DllCall("SystemParametersInfo",UInt,SPI_SETACTIVEWINDOWTRACKING,UInt,0,UInt,enabled,UInt,SPIF_UPDATEINIFILE | SPIF_SENDCHANGE)
;}

RemoteLogin1()
{
    global Home, Work
    if Home
    {
        Run C:\cygwin64\bin\mintty.exe -w max /usr/bin/ssh chris@192.168.1.101
    }
    if Work
    {
        Run C:\cygwin64\bin\mintty.exe -w max /usr/bin/ssh chris@192.168.56.101
    }
}

WorkLogin(server)
{
    SetWinDelay 10
    Run C:\cygwin64\bin\mintty.exe -w max -i /Cygwin-Terminal.ico --title mintty /usr/bin/ssh cwatrous@%server%
    WinWait mintty
    SendInput . .bashrc{Enter}
}

StartOctave()
{
    Run C:\cygwin64\bin\mintty.exe --title mintty -w max -i /Cygwin-Terminal.ico -
    WinWait mintty
    SendInput octave -q{Enter}
}

ClipText()
{
    clipboard = %clipboard%
}

#NoEnv
#Persistent
if FileExist("C:/Users/Chris") != ""
{
    Home = 1
    WordProcessor = C:\Program Files (x86)\LibreOffice 4\program\swriter.exe
    Spreadsheet = C:\Program Files (x86)\LibreOffice 4\program\scalc.exe
    VisualStudio = C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\devenv.exe
    VisualStudioProjects = Explorer C:\Users\chris\Documents\Visual Studio 2012\Projects
    GoogleEarth = C:\Program Files (x86)\Google\Google Earth\client\googleearth.exe
}
if FileExist("C:/Users/IBM_ADMIN") != ""
{
    Work = 1
    WordProcessor = C:\Program Files (x86)\OpenOffice 4\program\swriter.exe
    Spreadsheet = C:\Program Files (x86)\OpenOffice 4\program\scalc.exe
    GoogleEarth = C:\Program Files (x86)\Google\Google Earth Pro\client\googleearth.exe
}
Return

^Capslock::Capslock
Capslock::LCtrl

!#a::Run "C:\Program Files (x86)\Vim\vim74\gvim.exe" %A_MyDocuments%/AutoHotkey.ahk
^#a::Run AutoHotkey

;#a::Run
#c::Run Chrome
#g::Run %GoogleEarth%
#h::Run C:\cygwin64\bin\mintty.exe -w max -i /Cygwin-Terminal.ico -
#+h::Run %A_MyDocuments%/../Program Files/Cygwin-setup-x86_64.exe
#j::RemoteLogin1()
#+j::RemoteLogin2()
#^j::RemoteLogin3()
#n::Run Notepad
#o::StartOctave()
#q::Run Explorer %A_MyDocuments%\stuff
#s::Run acrord32
#v::Run C:\Program Files (x86)\JetBrains\PyCharm Community Edition 4.5.1\bin\pycharm.exe
#w::Run %WordProcessor%
#x::Run %Spreadsheet%
#y::Run powershell
#^y::Run cmd
#+y::Run "C:\Program Files (x86)\Vim\vim74\gvim.exe" C:\Users\Chris\Documents\WindowsPowerShell\profile.ps1
#z::Run Firefox
#]::WinMinimize A

+Space::_

; Unused Keys Win+Key combinations
;#Escape
;#k
;#`
;#,
;#i
;#.
;#;
;#/
;#[
;#'
;#]
;#\
;#Backspace
;#Enter
#Insert::ClipText()
;#Delete
;#Home
;#End
;#PageDown
;#PageUp

; Don't use these key combinations
;#e opens explorer
;#d shows desktop
;#r opens run dialog
;#f opens windows search
;#t focuses task bar
;#b focuses notification area
;#u opens ease of use control panel
;#m opens start menu along with program
;#l locks workstation when regular windows key is used
;#p opens some kind of screen management menu
;win + top row numberkeys, selects programs from the task bar
;#- windows magnifier zoom out
;#= windows magnifier zoom in
;#Space
;win + arrow keys, manipulates windows

#Numpad0::PlaceActiveWindow(0, 0, 1, 1)

#Numpad1::PlacePattern1()
PlacePattern1()
{
    global LastPattern
    global Spot
    if (LastPattern != 1)
        Spot := -1
    LastPattern := 1
    Spot := mod(Spot + 1, 2)
    if (Spot == 0)
        PlaceActiveWindow(0, 0, 1, 1/2)
    if (Spot == 1)
        PlaceActiveWindow(0, 1/2, 1, 1/2)
}

#Numpad2::PlacePattern2()
PlacePattern2()
{
    global LastPattern
    global Spot
    if (LastPattern != 2)
        Spot := -1
    LastPattern := 2
    Spot := mod(Spot + 1, 2)
    if (Spot == 0)
        PlaceActiveWindow(0, 0, 1/2, 1)
    if (Spot == 1)
        PlaceActiveWindow(1/2, 0, 1/2, 1)
}

#Numpad3::PlacePattern3()
PlacePattern3()
{
    global LastPattern
    global Spot
    if (LastPattern != 3)
        Spot := -1
    LastPattern := 3
    Spot := mod(Spot + 1, 4)
    if (Spot == 0)
        PlaceActiveWindow(0, 0, 1/2, 1/2)
    if (Spot == 1)
        PlaceActiveWindow(1/2, 0, 1/2, 1/2)
    if (Spot == 2)
        PlaceActiveWindow(0, 1/2, 1/2, 1/2)
    if (Spot == 3)
        PlaceActiveWindow(1/2, 1/2, 1/2, 1/2)
}

#Numpad4::PlacePattern4()
PlacePattern4()
{
    global LastPattern
    global Spot
    if (LastPattern != 4)
        Spot := -1
    LastPattern := 4
    Spot := mod(Spot + 1, 2)
    if (Spot == 0)
        PlaceActiveWindow(0, 0, 1, 2/3)
    if (Spot == 1)
        PlaceActiveWindow(0, 2/3, 1, 1/3)
}

#Numpad5::PlacePattern5()
PlacePattern5()
{
    global LastPattern
    global Spot
    if (LastPattern != 5)
        Spot := -1
    LastPattern := 5
    Spot := mod(Spot + 1, 2)
    if (Spot == 0)
        PlaceActiveWindow(0, 0, 1, 3/4)
    if (Spot == 1)
        PlaceActiveWindow(0, 3/4, 1, 1/4)
}

#`::ToggleWindowBorder()
#\::ToggleWindowBorder()
ToggleWindowBorder()
{
    SetWinDelay 10
    WinGet state, MinMax, A
    if (state == 1)
        PlaceActiveWindow(0, 0, 1, 1)
    WinSet Style, ^0x840000, A
    WinGetPos X, Y, Width, Height, A
    WinMove A, , X, Y, Width, Height + 1
    WinMove A, , X, Y, Width, Height
}

;#^f::ToggleFocusFollow()
;FocusFollow = 0
;ToggleFocusFollow()
;{
;    global FocusFollow
;    FocusFollow := !FocusFollow
;    SetFocusFollow(FocusFollow)
;}
;SetFocusFollow(enabled)
;{
;    SPI_SETACTIVEWINDOWTRACKING = 0x1001
;    SPIF_UPDATEINIFILE = 1
;    SPIF_SENDCHANGE = 2
;    DllCall("SystemParametersInfo",UInt,SPI_SETACTIVEWINDOWTRACKING,UInt,0,UInt,enabled,UInt,SPIF_UPDATEINIFILE | SPIF_SENDCHANGE)
;}

RemoteLogin1()
{
    global Home, Work
    if Home
    {
        Run C:\cygwin64\bin\mintty.exe -w max /usr/bin/ssh chris@192.168.1.100
    }
    if Work
    {
        Run C:\cygwin64\bin\mintty.exe -w max /usr/bin/ssh chris@192.168.56.101
    }
}

RemoteLogin2()
{
    global Work
    if Home
    {
        Run C:\cygwin64\bin\mintty.exe -w max -i /Cygwin-Terminal.ico /usr/bin/ssh chris@192.168.56.101
    }
    if Work
    {
        WorkLogin("t14hstbuild04")
    }
}

RemoteLogin3()
{
    global Work
    if Work
    {
        WorkLogin("peologin06")
    }
}

WorkLogin(server)
{
    SetWinDelay 10
    Run C:\cygwin64\bin\mintty.exe -w max -i /Cygwin-Terminal.ico --title mintty /usr/bin/ssh cwatrous@%server%
    WinWait mintty
    SendInput . .bashrc{Enter}
}

StartOctave()
{
    Run C:\cygwin64\bin\mintty.exe --title mintty -w max -i /Cygwin-Terminal.ico -
    WinWait mintty
    SendInput octave -q{Enter}
}

ClipText()
{
    clipboard = %clipboard%
}