bugfix with autohotkey settings

bugfix with autohotkey settings

^Tab::
Send #{Tab}
return

^!o::
IfWinActive, ahk_exe Obsidian.exe
    sleep 10
else
    WinShow ahk_exe Obsidian.exe
    WinActivate ahk_exe Obsidian.exe
    sleep 10
    WinSet Top
return

^!g::
IfWinActive, ahk_exe msedge.exe
    sleep 10
else
;    WinShow ahk_exe msedge.exe
;    WinActivate ahk_exe msedge.exe
;    sleep 10
;    WinSet Top
;    MouseClick
    sleep 10
    Send #0
return

^!m::
IfWinActive, ahk_exe chrome.exe
    sleep 10
else
    WinShow ahk_exe chrome.exe
    WinActivate ahk_exe chrome.exe
    sleep 10
    WinSet Top
return

^!Space::
Process,close,explorer.exe
sleep 50 ;This sleep 5000 is to let you see what actually happens. Decrease it later
run, explorer.exe
WinWait, ahk_class CabinetWClass
WinClose ;close the new explorer window
return

^Tab::
Send #{Tab}
return

^!o::
IfWinActive, ahk_exe Obsidian.exe
    sleep 10
else
    WinShow ahk_exe Obsidian.exe
    WinActivate ahk_exe Obsidian.exe
    sleep 10
    WinSet Top
return

^!g::
IfWinActive, ahk_exe msedge.exe
    sleep 10
else
;    WinShow ahk_exe msedge.exe
;    WinActivate ahk_exe msedge.exe
;    sleep 10
;    WinSet Top
;    MouseClick
    Send #0
return

^!m::
IfWinActive, ahk_exe chrome.exe
    sleep 10
else
    WinShow ahk_exe chrome.exe
    WinActivate ahk_exe chrome.exe
    sleep 10
    WinSet Top
return

^!Space::
Process,close,explorer.exe
sleep 50 ;This sleep 5000 is to let you see what actually happens. Decrease it later
run, explorer.exe
WinWait, ahk_class CabinetWClass
WinClose ;close the new explorer window
return


MM hotkeys

MM hotkeys

; emulate term
^[::Send {Esc}

; below is adapted from https://autohotkey.com/board/topic/51959-using-capslock-as-another-modifier-key/

$*Capslock::
Gui, 99:+ToolWindow
Gui, 99:Show, NoActivate, Capslock Is Down
keywait, Capslock
Gui, 99:Destroy
return

#IfWinExist, Capslock Is Down

; vimish
h::Left
j::Down
k::Up
l::Right
; could try to be vimish on these, but can't really do $ ctrl-b etc. with left pinky already on capslock
u::Home
m::End
i::PgUp
,::PgDn
BackSpace::Del

; multimedia
q::Media_Prev
w::Media_Play_Pause
e::Media_Next
1::Volume_Down
2::Volume_Mute
3::Volume_Up

#IfWinExist

; work around accidental ctrl-shift-q in firefox
$^+q::
IfWinNotActive, ahk_exe firefox.exe
{
    Send ^+q ; this is not Firefox, so send the key again.
}

; emulate term
^[::Send {Esc}

; below is adapted from https://autohotkey.com/board/topic/51959-using-capslock-as-another-modifier-key/

$*Capslock::
Gui, 99:+ToolWindow
Gui, 99:Show, NoActivate, Capslock Is Down
keywait, Capslock
Gui, 99:Destroy
return

#IfWinExist, Capslock Is Down
; vimish
h::Left
j::Down
k::Up
l::Right
; could try to be vimish on these, but can't really do $ with left pinky already on capslock
u::Home
m::End
i::PgUp
,::PgDn
BackSpace::Del
#IfWinExist

; work around accidental ctrl-shift-q in firefox
$^+q::
IfWinNotActive, ahk_exe firefox.exe
{
    Send ^+q ; this is not Firefox, so send the key again.
}


enable MClick

enable MClick

;#### wheelctrl.ahk
EnvGet, DebugP, DEBUG
If (DebugP)
{
  TrayTip, Loading %A_ScriptName% , Debug Mode On
}
Else
{
  Menu, Tray, NoIcon
}
return

#Persistent
;---------------------------------------------------------------
MButton::
  Scale := 10
  MouseGetPos, X0, Y0
  fn := Func("SendWheelEvent").bind(Y0, Scale)
  SetTimer, % fn, 100
return

MButton Up::
  MouseGetPos, X1, Y1
  SetTimer, % fn, Off
  if (X1 == X0)  ; trigger middle click if cursor is not moved.
    MouseClick, Middle
return

SendWheelEvent(Y0, Scale)
{
  MouseGetPos, X, NewY
  Delta := NewY - Y0
  NumWheel := abs(Delta // Scale)
  If (NumWheel == 0)
    return
  WheelMove := (Delta > 0 ?  "WheelDown" : "WheelUp")

  Loop % NumWheel {
    Click, %WheelMove%
  }

  MouseMove, X, Y0
  ;Traytip, evt: %WheelMove% x %NumWheel%, mouse moving
  ;ListVars
  return
}

#If DebugP
!^r::Reload

;#### wheelctrl.ahk
EnvGet, DebugP, DEBUG
If (DebugP)
{
  TrayTip, Loading %A_ScriptName% , Debug Mode On
}
Else
{
  Menu, Tray, NoIcon
}
return

#Persistent
;---------------------------------------------------------------
MButton::
  Scale := 5
  MouseGetPos,, Y0
  fn := Func("SendWheelEvent").bind(Y0, Scale)
  SetTimer, % fn, 100
return

MButton Up::
  MouseGetPos,, Y1
  SetTimer, % fn, Off
  if (Y1 - Y0 == 0)  ; trigger middle click if cursor is not moved.
    MouseClick, Middle
return

SendWheelEvent(Y0, Scale)
{
  MouseGetPos,, NewY
  Delta := NewY - Y0
  NumWheel := abs(Delta // Scale)
  If (NumWheel == 0)
    return
  WheelMove := (Delta > 0 ?  "WheelDown" : "WheelUp")

  Loop % NumWheel {
    Click, %WheelMove%
  }

  ;Traytip, evt: %WheelMove% x %NumWheel%, mouse moving
  ;ListVars
  return
}

#If DebugP
!^r::Reload


testing things

testing things

#NoEnv
#SingleInstance off
#NoTrayIcon
SendMode Input
SetWorkingDir %A_ScriptDir%

;Some parts from Lexikos' Installer.ahk

OnExit,GuiClose

MYAPP_NAME:="Webapp.ahk"
MYAPP_PROTOCOL:="myapp"

HTML_page =
( Ltrim Join
<!DOCTYPE html>

Lorem Ipsum

Welcome!

The standard Lorem Ipsum passage, used since the 1500s

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

		<textarea rows="4" cols="70" id="MyTextBox">1234567890-=\ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!@#$^&*()_+|~</textarea>

			Click me for a MsgBox -
			Click me for nothing -
			Click me for a ding sound!

			Link using onlick instead

			<input type="button" id="MyButton1" value="Show Content in AHK MsgBox">
			<input type="button" id="MyButton2" value="Change Content with AHK">
			<input type="button" id="MyButton3" value="Greetings from AHK">
			<input type="button" id="MyButton4" value="AHK MsgBox using function" onclick="AHK('RunButton4_function')">

)

Gui Margin, 0, 0
Gui +LastFound

OnMessage(0x100, "gui_KeyDown", 2)
Gui Add, ActiveX, vwb w640 h480 hwndhwb, Shell.Explorer
wb.silent := true ;Surpress JS Error boxes
Display(wb,HTML_page)
ComObjConnect(wb, wb_events)

DisableClickSounds()

w := wb.Document.parentWindow
w.AHK := Func("JS_AHK")

;Wait for IE to load the page, before we connect the event handlers
while wb.readystate != 4 or wb.busy
	sleep 10

;Use DOM access just like javascript!
MyButton1 := wb.document.getElementById("MyButton1")
MyButton2 := wb.document.getElementById("MyButton2")
MyButton3 := wb.document.getElementById("MyButton3")
ComObjConnect(MyButton1, "MyButton1_") ;connect button events
ComObjConnect(MyButton2, "MyButton2_")
ComObjConnect(MyButton3, "MyButton3_")

Gui Show, w640 h480, %MYAPP_NAME%
return

GuiEscape:
	MsgBox 0x34, Webapp.ahk, Are you sure you want to quit?
	IfMsgBox No
		return
GuiClose:
	Gui Destroy
	FileDelete,%A_Temp%\*.DELETEME.html ;clean tmp file
	ExitApp
return

class wb_events
{
	;for more events and other, see http://msdn.microsoft.com/en-us/library/aa752085

	NavigateComplete2(wb) { ;blocked all navigation, we want our own stuff happening
		wb.Stop()
	}
	DownloadComplete(wb, NewURL) {
		wb.Stop()
	}
	DocumentComplete(wb, NewURL) {
		wb.Stop()
	}

	BeforeNavigate2(wb, NewURL)
	{
		wb.Stop() ;blocked all navigation, we want our own stuff happening
		;parse the url
		global MYAPP_PROTOCOL
		if (InStr(NewURL,MYAPP_PROTOCOL "://")==1) { ;if url starts with "myapp://"
			what := SubStr(NewURL,Strlen(MYAPP_PROTOCOL)+4) ;get stuff after "myapp://"
			if InStr(what,"msgbox/hello")
				MsgBox Hello world!
			else if InStr(what,"soundplay/ding")
				SoundPlay, %A_WinDir%\Media\ding.wav
		}
		;else do nothing
	}
}

; Our Event Handlers
MyButton1_OnClick() {
	global wb
	MsgBox % wb.Document.getElementById("MyTextBox").Value
}
MyButton2_OnClick() {
	global wb
	FormatTime, TimeString, %A_Now%, dddd MMMM d, yyyy HH:mm:ss
	data := "AHK Version " A_AhkVersion " - " (A_IsUnicode ? "Unicode" : "Ansi") " " (A_PtrSize == 4 ? "32" : "64") "bit`nCurrent time: " TimeString "`nRandom number: " RandNum()
	wb.Document.getElementById("MyTextBox").value := data
}
MyButton3_OnClick() {
	MsgBox Hello world!
}

RunButton4_function() {
	MsgBox Hello from JS_AHK :)
}

Display(wb,html_str) {
	Count:=0
	while % FileExist(f:=A_Temp "\" A_TickCount A_NowUTC "-tmp" Count ".DELETEME.html")
		Count+=1
	FileAppend,%html_str%,%f%
	wb.Navigate("file://" . f)
}

RandNum(min=0,max=65535) {
	Random, x, %min%, %max%
	return x
}

DisableClickSounds() {
	FEATURE_DISABLE_NAVIGATION_SOUNDS := 21
	SET_FEATURE_ON_PROCESS := 0x00000002
    DllCall("urlmon.dll\CoInternetSetFeatureEnabled","uint",FEATURE_DISABLE_NAVIGATION_SOUNDS,"uint",SET_FEATURE_ON_PROCESS,1)
}

_InitUI() {
    local w
    SetWBClientSite()
    ;gosub DefineUI
    wb.Silent := true
    wb.Navigate("about:blank")
    while wb.ReadyState != 4 {
        Sleep 10
        if (A_TickCount-initTime > 2000)
            throw 1
    }
    wb.Document.open()
    wb.Document.write(html)
    wb.Document.close()
    w := wb.Document.parentWindow
    if !w || !w.initOptions
        throw 1
    w.AHK := Func("JS_AHK")
    if (!CurrentType && A_ScriptDir != DefaultPath)
        CurrentName := ""  ; Avoid showing the Reinstall option since we don't know which version it was.
    w.initOptions(CurrentName, CurrentVersion, CurrentType
                , ProductVersion, DefaultPath, DefaultStartMenu
                , DefaultType, A_Is64bitOS = 1)
    if (A_ScriptDir = DefaultPath) {
        w.installdir.disabled := true
        w.installdir_browse.disabled := true
        w.installcompiler.disabled := !DefaultCompiler
        w.installcompilernote.style.display := "block"
        w.ci_nav_install.innerText := "apply"
        w.install_button.innerText := "Apply"
        w.extract.style.display := "None"
        w.opt1.disabled := true
        w.opt1.firstChild.innerText := "Checking for updates..."
    }
    w.installcompiler.checked := DefaultCompiler
    w.enabledragdrop.checked := DefaultDragDrop
    w.separatebuttons.checked := DefaultIsHostApp
    ; w.defaulttoutf8.checked := DefaultToUTF8
    if !A_Is64bitOS
        w.it_x64.style.display := "None"
    if A_OSVersion in WIN_2000,WIN_2003,WIN_XP ; i.e. not WIN_7, WIN_8 or a future OS.
        w.separatebuttons.parentNode.style.display := "none"
    ;w.switchPage("start")
    w.document.body.focus()
    ; Scale UI by screen DPI.  My testing showed that Vista with IE7 or IE9
    ; did not scale by default, but Win8.1 with IE10 did.  The scaling being
    ; done by the control itself = deviceDPI / logicalDPI.
    logicalDPI := w.screen.logicalXDPI, deviceDPI := w.screen.deviceXDPI
    if (A_ScreenDPI != 96)
        w.document.body.style.zoom := A_ScreenDPI/96 * (logicalDPI/deviceDPI)
    ;if (A_ScriptDir = DefaultPath)
    ;    CheckForUpdates()
}

/*  Complex workaround to override "Active scripting" setting
 *  and ensure scripts can run within the WebBrowser control.
 */

global WBClientSite

SetWBClientSite()
{
    interfaces := {
    (Join,
        IOleClientSite: [0,3,1,0,1,0]
        IServiceProvider: [3]
        IInternetSecurityManager: [1,1,3,4,8,7,3,3]
    )}
    unkQI      := RegisterCallback("WBClientSite_QI", "Fast")
    unkAddRef  := RegisterCallback("WBClientSite_AddRef", "Fast")
    unkRelease := RegisterCallback("WBClientSite_Release", "Fast")
    WBClientSite := {_buffers: bufs := {}}, bufn := 0,
    for name, prms in interfaces
    {
        bufn += 1
        bufs.SetCapacity(bufn, (4 + prms.MaxIndex()) * A_PtrSize)
        buf := bufs.GetAddress(bufn)
        NumPut(unkQI,       buf + 1*A_PtrSize)
        NumPut(unkAddRef,   buf + 2*A_PtrSize)
        NumPut(unkRelease,  buf + 3*A_PtrSize)
        for i, prmc in prms
            NumPut(RegisterCallback("WBClientSite_" name, "Fast", prmc+1, i), buf + (3+i)*A_PtrSize)
        NumPut(buf + A_PtrSize, buf + 0)
        WBClientSite[name] := buf
    }
    global wb
    if pOleObject := ComObjQuery(wb, "{00000112-0000-0000-C000-000000000046}")
    {   ; IOleObject::SetClientSite
        DllCall(NumGet(NumGet(pOleObject+0)+3*A_PtrSize), "ptr"
            , pOleObject, "ptr", WBClientSite.IOleClientSite, "uint")
        ObjRelease(pOleObject)
    }
}

WBClientSite_QI(p, piid, ppvObject)
{
    static IID_IUnknown := "{00000000-0000-0000-C000-000000000046}"
    static IID_IOleClientSite := "{00000118-0000-0000-C000-000000000046}"
    static IID_IServiceProvider := "{6d5140c1-7436-11ce-8034-00aa006009fa}"
    iid := _String4GUID(piid)
    if (iid = IID_IOleClientSite || iid = IID_IUnknown)
    {
        NumPut(WBClientSite.IOleClientSite, ppvObject+0)
        return 0 ; S_OK
    }
    if (iid = IID_IServiceProvider)
    {
        NumPut(WBClientSite.IServiceProvider, ppvObject+0)
        return 0 ; S_OK
    }
    NumPut(0, ppvObject+0)
    return 0x80004002 ; E_NOINTERFACE
}

WBClientSite_AddRef(p)
{
    return 1
}

WBClientSite_Release(p)
{
    return 1
}

WBClientSite_IOleClientSite(p, p1="", p2="", p3="")
{
    if (A_EventInfo = 3) ; GetContainer
    {
        NumPut(0, p1+0) ; *ppContainer := NULL
        return 0x80004002 ; E_NOINTERFACE
    }
    return 0x80004001 ; E_NOTIMPL
}

WBClientSite_IServiceProvider(p, pguidService, piid, ppvObject)
{
    static IID_IUnknown := "{00000000-0000-0000-C000-000000000046}"
    static IID_IInternetSecurityManager := "{79eac9ee-baf9-11ce-8c82-00aa004ba90b}"
    if (_String4GUID(pguidService) = IID_IInternetSecurityManager)
    {
        iid := _String4GUID(piid)
        if (iid = IID_IInternetSecurityManager || iid = IID_IUnknown)
        {
            NumPut(WBClientSite.IInternetSecurityManager, ppvObject+0)
            return 0 ; S_OK
        }
        NumPut(0, ppvObject+0)
        return 0x80004002 ; E_NOINTERFACE
    }
    NumPut(0, ppvObject+0)
    return 0x80004001 ; E_NOTIMPL
}

WBClientSite_IInternetSecurityManager(p, p1="", p2="", p3="", p4="", p5="", p6="", p7="", p8="")
{
    if (A_EventInfo = 5) ; ProcessUrlAction
    {
        if (p2 = 0x1400) ; dwAction = URLACTION_SCRIPT_RUN
        {
            NumPut(0, p3+0)  ; *pPolicy := URLPOLICY_ALLOW
            return 0 ; S_OK
        }
    }
    return 0x800C0011 ; INET_E_DEFAULT_ACTION
}

_String4GUID(pGUID)
{
	VarSetCapacity(String,38*2)
	DllCall("ole32\StringFromGUID2", "ptr", pGUID, "str", String, "int", 39)
	Return	String
}

/*  Fix keyboard shortcuts in WebBrowser control.
 *  References:
 *    http://www.autohotkey.com/community/viewtopic.php?p=186254#p186254
 *    http://msdn.microsoft.com/en-us/library/ms693360
 */

gui_KeyDown(wParam, lParam, nMsg, hWnd) {
    global wb
    if (Chr(wParam) ~= "[A-Z]" || wParam = 0x74) ; Disable Ctrl+O/L/F/N and F5.
        return
    pipa := ComObjQuery(wb, "{00000117-0000-0000-C000-000000000046}")
    VarSetCapacity(kMsg, 48), NumPut(A_GuiY, NumPut(A_GuiX
    , NumPut(A_EventInfo, NumPut(lParam, NumPut(wParam
    , NumPut(nMsg, NumPut(hWnd, kMsg)))), "uint"), "int"), "int")
    Loop 2
    r := DllCall(NumGet(NumGet(1*pipa)+5*A_PtrSize), "ptr", pipa, "ptr", &kMsg)
    ; Loop to work around an odd tabbing issue (it's as if there
    ; is a non-existent element at the end of the tab order).
    until wParam != 9 || wb.Document.activeElement != ""
    ObjRelease(pipa)
    if r = 0 ; S_OK: the message was translated to an accelerator.
        return 0
}

/*  javascript:AHK('Func') --> Func()
 */

JS_AHK(func, prms*) {
    global wb
    ; Stop navigation prior to calling the function, in case it uses Exit.
    wb.Stop(),  %func%(prms*)
}

/*  Utility Functions
 */

getWindow() {
    global wb
    return wb.document.parentWindow
}

ErrorExit(errMsg) {
    global
    if !SilentMode
        MsgBox 16, Webapp.ahk, %errMsg%
    ExitApp 1
}

GetErrorMessage(error_code="") {
    VarSetCapacity(buf, 1024) ; Probably won't exceed 1024 chars.
    if DllCall("FormatMessage", "uint", 0x1200, "ptr", 0, "int", error_code!=""
                ? error_code : A_LastError, "uint", 1024, "str", buf, "uint", 1024, "ptr", 0)
        return buf
}

Quit() {
    ExitApp
}

#NoEnv
SendMode Input
SetWorkingDir %A_ScriptDir%

;// examples from https://autohotkey.com/boards/viewtopic.php?f=7&t=4588

;activex gui - test  joedf - 2014/07/04
#SingleInstance, off
OnExit,OnExit

MYAPP_PROTOCOL:="myapp"

HTML_page =
( Ltrim Join
<!DOCTYPE html>

Lorem Ipsum

Welcome!

The standard Lorem Ipsum passage, used since the 1500s

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

			Click me for a MsgBox -
			Click me for nothing -
			Click me for a ding sound!

)

Gui Add, ActiveX, x0 y0 w640 h480 vWB, Shell.Explorer  ; The final parameter is the name of the ActiveX component.
WB.silent := true ;Surpress JS Error boxes
Display(WB,HTML_page)
ComObjConnect(WB, WB_events)  ; Connect WB's events to the WB_events class object.
Gui Show, w640 h480
return

GuiClose:
ExitApp

OnExit:
	FileDelete,%A_Temp%\*.DELETEME.html ;clean tmp file
ExitApp

class WB_events
{
	;for more events and other, see http://msdn.microsoft.com/en-us/library/aa752085

	NavigateComplete2(wb) {
		wb.Stop() ;blocked all navigation, we want our own stuff happening
	}
	DownloadComplete(wb, NewURL) {
		wb.Stop() ;blocked all navigation, we want our own stuff happening
	}
	DocumentComplete(wb, NewURL) {
		wb.Stop() ;blocked all navigation, we want our own stuff happening
	}

	BeforeNavigate2(wb, NewURL)
	{
		wb.Stop() ;blocked all navigation, we want our own stuff happening
		;parse the url
		global MYAPP_PROTOCOL
		if (InStr(NewURL,MYAPP_PROTOCOL "://")==1) { ;if url starts with "myapp://"
			what := SubStr(NewURL,Strlen(MYAPP_PROTOCOL)+4) ;get stuff after "myapp://"
			if InStr(what,"msgbox/hello")
				MsgBox Hello world!
			else if InStr(what,"soundplay/ding")
				SoundPlay, %A_WinDir%\Media\ding.wav
		}
		;else do nothing
	}
}

Display(WB,html_str) {
	Count:=0
	while % FileExist(f:=A_Temp "\" A_TickCount A_NowUTC "-tmp" Count ".DELETEME.html")
		Count+=1
	FileAppend,%html_str%,%f%
	WB.Navigate("file://" . f)
}

;activex gui 2 - test  joedf - 2014/09/19
#SingleInstance, off
OnExit,OnExit

HTML_page =
( Ltrim Join
<!DOCTYPE html>

Hello World

		<textarea rows="4" cols="70" id="MyTextBox">1234567890-=\ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!@#$^&*()_+|~</textarea>

			<input type="button" id="MyButton1" value="Show Content in AHK MsgBox">
			<input type="button" id="MyButton2" value="Change Content with AHK">
			<input type="button" id="MyButton3" value="Greetings from AHK">

)

Gui Add, ActiveX, x0 y0 w640 h480 vWB, Shell.Explorer  ; The final parameter is the name of the ActiveX component.
WB.silent := true ;Surpress JS Error boxes
Display(WB,HTML_page)

;Wait for IE to load the page, before we connect the event handlers
while WB.readystate != 4 or WB.busy
	sleep 10

;Use DOM access just like javascript!
MyButton1 := wb.document.getElementById("MyButton1")
MyButton2 := wb.document.getElementById("MyButton2")
MyButton3 := wb.document.getElementById("MyButton3")
ComObjConnect(MyButton1, "MyButton1_") ;connect button events
ComObjConnect(MyButton2, "MyButton2_")
ComObjConnect(MyButton3, "MyButton3_")
Gui Show, w640 h480
return

GuiClose:
ExitApp
OnExit:
	FileDelete,%A_Temp%\*.DELETEME.html ;clean tmp file
ExitApp

; Our Event Handlers
MyButton1_OnClick() {
	global wb
	MsgBox % wb.Document.getElementById("MyTextBox").Value
}
MyButton2_OnClick() {
	global wb
	FormatTime, TimeString, %A_Now%, dddd MMMM d, yyyy HH:mm:ss
	data := "AHK Version " A_AhkVersion " - " (A_IsUnicode ? "Unicode" : "Ansi") " " (A_PtrSize == 4 ? "32" : "64") "bit`nCurrent time: " TimeString
	wb.Document.getElementById("MyTextBox").value := data
}
MyButton3_OnClick() {
	MsgBox Hello world!
}
;------------------
Display(WB,html_str) {
	Count:=0
	while % FileExist(f:=A_Temp "\" A_TickCount A_NowUTC "-tmp" Count ".DELETEME.html")
		Count+=1
	FileAppend,%html_str%,%f%
	WB.Navigate("file://" . f)
}


foobar2000 plugin: prompt mode

foobar2000 plugin: prompt mode

foobar2000:
    global foobar2000_class := "{97E27FAA-C0B3-4b8e-A693-ED7881E99FC1}"

    ; insert模式
    vim.mode("insert", foobar2000_class)
    vim.map("<esc>", "<Normal_Mode_foobar2000>", foobar2000_class)

    ; normal模式
    vim.mode("normal", foobar2000_class)

    vim.map("i", "<Insert_Mode_foobar2000>", foobar2000_class)

    vim.map("0", "<0>", foobar2000_class)
    vim.map("1", "<1>", foobar2000_class)
    vim.map("2", "<2>", foobar2000_class)
    vim.map("3", "<3>", foobar2000_class)
    vim.map("4", "<4>", foobar2000_class)
    vim.map("5", "<5>", foobar2000_class)
    vim.map("6", "<6>", foobar2000_class)
    vim.map("7", "<7>", foobar2000_class)
    vim.map("8", "<8>", foobar2000_class)
    vim.map("9", "<9>", foobar2000_class)

    vim.map("j", "<down>", foobar2000_class)
    vim.map("k", "<up>", foobar2000_class)
    vim.map("l", "<enter>", foobar2000_class)
    vim.map("gg", "<home>", foobar2000_class)
    vim.map("G", "<end>", foobar2000_class)
    vim.map("<ctrl>f", "<pgdn>", foobar2000_class)
    vim.map("<ctrl>b", "<pgup>", foobar2000_class)
    vim.map("/", "<foobar2000_search>", foobar2000_class)
    vim.map("t", "<foobar2000_tree>", foobar2000_class)
    vim.map("m", "<foobar2000_list>", foobar2000_class)
    vim.map("n", "<Media_Next>", foobar2000_class)
    vim.map("p", "<Media_Prev>", foobar2000_class)
    vim.map("s", "<Media_Stop>", foobar2000_class)

    vim.map("gn", "<NextTab>", foobar2000_class)
    vim.map("gp", "<PrevTab>", foobar2000_class)

    vim.Comment("<Normal_Mode_foobar2000>", "进入normal模式")
    vim.Comment("<Insert_Mode_foobar2000>", "进入insert模式")
    vim.Comment("<foobar2000_search>", "打开搜索窗口")
    vim.Comment("<foobar2000_tree>", "定位到目录窗口")
    vim.Comment("<foobar2000_list>", "定位到播放列表")
return

<Normal_Mode_foobar2000>:
    ToolTip % "进入 normal 模式"
    SetTimer, <RemoveToolTip>, 600
    vim.mode("normal", foobar2000_class)
return

<Insert_Mode_foobar2000>:
    ToolTip % "进入 insert 模式"
    SetTimer, <RemoveToolTip>, 600
    vim.mode("insert", foobar2000_class)
return

<foobar2000_search>:
    send ^f
return

<foobar2000_tree>:
    ControlFocus, SysTreeView321
return

<foobar2000_list>:
    ControlFocus, {4B94B650-C2D8-40de-A0AD-E8FADF62D56C}1
return

foobar2000:
    global foobar2000_class := "{97E27FAA-C0B3-4b8e-A693-ED7881E99FC1}"

    ; insert模式
    vim.mode("insert", foobar2000_class)
    vim.map("<esc>", "<Normal_Mode_foobar2000>", foobar2000_class)

    ; normal模式
    vim.mode("normal", foobar2000_class)

    vim.map("i", "<Insert_Mode_foobar2000>", foobar2000_class)

    vim.map("0", "<0>", foobar2000_class)
    vim.map("1", "<1>", foobar2000_class)
    vim.map("2", "<2>", foobar2000_class)
    vim.map("3", "<3>", foobar2000_class)
    vim.map("4", "<4>", foobar2000_class)
    vim.map("5", "<5>", foobar2000_class)
    vim.map("6", "<6>", foobar2000_class)
    vim.map("7", "<7>", foobar2000_class)
    vim.map("8", "<8>", foobar2000_class)
    vim.map("9", "<9>", foobar2000_class)

    vim.map("j", "<down>", foobar2000_class)
    vim.map("k", "<up>", foobar2000_class)
    vim.map("l", "<enter>", foobar2000_class)
    vim.map("gg", "<home>", foobar2000_class)
    vim.map("G", "<end>", foobar2000_class)
    vim.map("<ctrl>f", "<pgdn>", foobar2000_class)
    vim.map("<ctrl>b", "<pgup>", foobar2000_class)
    vim.map("/", "<foobar2000_search>", foobar2000_class)
    vim.map("t", "<foobar2000_tree>", foobar2000_class)
    vim.map("m", "<foobar2000_list>", foobar2000_class)
    vim.map("n", "<Media_Next>", foobar2000_class)
    vim.map("p", "<Media_Prev>", foobar2000_class)
    vim.map("s", "<Media_Stop>", foobar2000_class)

    vim.map("gn", "<NextTab>", foobar2000_class)
    vim.map("gp", "<PrevTab>", foobar2000_class)

    vim.Comment("<Normal_Mode_foobar2000>", "进入normal模式")
    vim.Comment("<Insert_Mode_foobar2000>", "进入insert模式")
    vim.Comment("<foobar2000_search>", "打开搜索窗口")
    vim.Comment("<foobar2000_tree>", "定位到目录窗口")
    vim.Comment("<foobar2000_list>", "定位到播放列表")
return

<Normal_Mode_foobar2000>:
    global foobar2000_class
    vim.mode("normal", foobar2000_class)
return

<Insert_Mode_foobar2000>:
    global foobar2000_class
    vim.mode("insert", foobar2000_class)
return

<foobar2000_search>:
    send ^f
return

<foobar2000_tree>:
    ControlFocus, SysTreeView321
return

<foobar2000_list>:
    ControlFocus, {4B94B650-C2D8-40de-A0AD-E8FADF62D56C}1
return


Expanded objects test to include dynamic creation of array indices.


RunZ: Add g_UseFallbackCommands

RunZ: Add g_UseFallbackCommands

#NoEnv
#SingleInstance, Force
#NoTrayIcon

FileEncoding, utf-8
SendMode Input

; 自动生成的命令文件
global g_SearchFileList := A_ScriptDir . "\SearchFileList.txt"
; 配置文件
global g_ConfFile := A_ScriptDir . "\RunZ.ini"

if !FileExist(g_ConfFile)
{
    FileCopy, %g_ConfFile%.help.txt, %g_ConfFile%
}

global g_Conf := class_EasyINI(g_ConfFile)

; 所有命令
global g_Commands
; 当搜索无结果时使用的命令
global g_FallbackCommands
; 当前是否使用着 g_FallbackCommands
global g_UseFallbackCommands
; 编辑框当前内容
global g_CurrentInput
; 当前匹配到的第一条命令
global g_CurrentCommand
; 当前匹配到的所有命令
global g_CurrentCommandList
; 是否启用 TCMatch
global g_EnableTCMatch = TCMatchOn(g_Conf.Config.TCMatchPath)
; 列表第一列的首字母或数字
global g_FirstChar := Asc(g_Conf.Gui.FirstChar)
; 在列表中显示的行数
global g_DisplayRows := g_Conf.Gui.DisplayRows
; 在列表中显示的文字列数（多出的会被截断）
global g_DisplayCols := g_Conf.Gui.DisplayCols
; 命令使用了显示框
global g_UseDisplay
; 当前输入命令的参数，数组，为了方便没有添加 g_ 前缀
global Arg

if (FileExist(g_SearchFileList))
{
    LoadFiles()
}
else
{
    GoSub, ReloadFiles
}

Gui, Main:Font, % "s" g_Conf.Gui.FontSize, % g_Conf.Gui.FontName
Gui, Main:Add, Edit, % "gProcessInputCommand vSearchArea"
        . " w" g_Conf.Gui.WidgetWidth " h" g_Conf.Gui.EditHeight,
Gui, Main:Add, Edit, % "ReadOnly vDisplayArea"
        . " w" g_Conf.Gui.WidgetWidth " h" g_Conf.Gui.DisplayAreaHeight
        , % SearchCommand("", true)
if (g_Conf.Gui.ShowCurrentCommand)
{
    Gui, Main:Add, Edit, % "ReadOnly"
        . " w" g_Conf.Gui.WidgetWidth " h" g_Conf.Gui.EditHeight,
}
Gui, Main:Show, , RunZ
if (g_Conf.Gui.HideTitle)
{
    WinSet, Style, -0xC00000, A
}

Hotkey, IfWinActive, RunZ
Hotkey, ~enter, RunCurrentCommand
Hotkey, ^j, ClearInput
Hotkey, f1, Help
Hotkey, f2, EditConfig
Hotkey, esc, ExitRunZ
Hotkey, ^d, OpenCurrentFileDir
Hotkey, ^x, DeleteCurrentFile
Hotkey, ^s, ShowCurrentFile
Hotkey, ^r, ReloadFiles

if (g_Conf.Config.RunInBackground)
{
    Hotkey, esc, WindowMin
}

Loop, % g_DisplayRows
{
    key := Chr(g_FirstChar + A_Index - 1)
    ; lalt +
    Hotkey, <!%key%, RunSelectedCommand1
    ; tab +
    Hotkey, ~%key%, RunSelectedCommand2
    ; shift +
    Hotkey, ~+%key%, AddCustomCommand
}

if (g_Conf.Config.SaveInputText && g_Conf.Auto.InputText != "")
{
    Send, % g_Conf.Auto.InputText
}

return

ExitRunZ:
    if (g_Conf.Config.SaveInputText)
    {
        g_Conf.DeleteKey("auto", "InputText")
        g_Conf.AddKey("auto", "InputText", g_CurrentInput)
        g_Conf.Save()
    }

    ExitApp
return

WindowMin:
    WinMinimize, A
return

GenerateSearchFileList()
{
    FileDelete, %g_SearchFileList%

    searchFileType := g_Conf.Config.SearchFileType

    for dirIndex, dir in StrSplit(g_Conf.Config.SearchFileDir, " | ")
    {
        if (InStr(dir, "A_") == 1)
        {
            searchPath := %dir%
        }
        else
        {
            searchPath := dir
        }

        for extIndex, ext in StrSplit(searchFileType, " | ")
        {
            Loop, Files, %searchPath%\%ext%, R
            {
                if (g_Conf.Config.SearchFileExclude != ""
                        && RegexMatch(A_LoopFileLongPath, g_Conf.Config.SearchFileExclude))
                {
                    continue
                }
                FileAppend, file | %A_LoopFileLongPath%`n, %g_SearchFileList%,
            }
        }
    }
}

ReloadFiles:
    GenerateSearchFileList()

    LoadFiles()
return

ProcessInputCommand:
    GuiControlGet, g_CurrentInput, , SearchArea
    SearchCommand(g_CurrentInput)
return

SearchCommand(command = "", firstRun = false)
{
    result := ""
    commandPrefix := SubStr(command, 1, 1)

    if (commandPrefix == ";" || commandPrefix == ":")
    {
        if (commandPrefix == ";")
        {
            g_CurrentCommand := g_FallbackCommands[1]
        }
        else if (commandPrefix == ":")
        {
            g_CurrentCommand := g_FallbackCommands[2]
        }

        g_CurrentCommandList.Insert(g_CurrentCommand)
        result .= "a | " . g_CurrentCommand
        Arg := SubStr(g_CurrentInput, 2)
        DisplaySearchResult(result)
        return result
    }
    ; 用空格来判断参数
    else if (InStr(command, " ") && g_CurrentCommand != "")
    {
        if (g_UseFallbackCommands)
        {
            Arg := command
        }
        else
        {
            Arg := SubStr(command, InStr(command, " ") + 1)
        }
        return
    }

    g_CurrentCommandList := Object()

    order := g_FirstChar

    for index, element in g_Commands
    {
        elementToSearch := StrSplit(element, " | ")[2]

        if (InStr(element, "file | ", true, 1))
        {
            ; 只搜不带扩展名的文件名
            SplitPath, elementToSearch, , fileDir, , fileNameNoExt
            elementToShow := SubStr("file | " . fileNameNoExt, 1, g_DisplayCols)

            if (g_Conf.Config.SearchFullPath)
            {
                ; TCMatch 在搜索路径时只搜索文件名，强行将 \ 转成空格
                elementToSearch := StrReplace(fileDir . "\" . fileNameNoExt, "\", " ")
            }
        }
        else
        {
            elementToShow := SubStr(element, 1, g_DisplayCols)
        }

        if (MatchCommand(elementToSearch, command))
        {
            g_CurrentCommandList.Insert(element)

            if (order == g_FirstChar)
            {
                g_CurrentCommand := element
            }
            else
            {
                result .= "`n"
            }

            result .= Chr(order++) . " | " . elementToShow

            if (order - g_FirstChar >= g_DisplayRows)
            {
                break
            }
            ; 第一次运行只加载 function 类型
            if (firstRun && (order - g_FirstChar >= g_DisplayRows - 4))
            {
                result .= "`n`n现有 " g_Commands.Length() " 条命令。"
                result .= "`n`n键入内容 搜索，回车 执行第一条，Alt + 字母 执行，F1 帮助，Esc 退出。"

                break
            }
        }
    }

    if (result == "")
    {
        g_UseFallbackCommands := true
        g_CurrentCommand := g_FallbackCommands[1]
        g_CurrentCommandList := g_FallbackCommands
        Arg := g_CurrentInput

        for index, element in g_FallbackCommands
        {
            if (index != 1)
            {
                result .= "`n"
            }

            result .= Chr(g_FirstChar - 1 + index++) . " | " . element
        }
    }
    else
    {
        g_UseFallbackCommands := false
    }

    DisplaySearchResult(result)
    return result
}

DisplaySearchResult(result)
{
    DisplayText(result)

    if (g_CurrentCommandList.Length() == 1 && g_Conf.Config.RunIfOnlyOne)
    {
        GoSub, RunCurrentCommand
    }

    if (g_Conf.Gui.ShowCurrentCommand)
    {
        ControlSetText, Edit3, %g_CurrentCommand%
    }
}

ClearInput:
    ControlSetText, Edit1,
return

RunCurrentCommand:
    if (g_CurrentInput != "")
    {
        g_UseDisplay := false

        RunCommand(g_CurrentCommand)
        if (g_Conf.Config.RunOnce && !g_UseDisplay)
        {
            GoSub, ExitRunZ
        }
    }
return

MatchCommand(Haystack, Needle)
{
    if (g_EnableTCMatch)
    {
        return TCMatch(Haystack, Needle)
    }

    return InStr(Haystack, Needle)
}

RunCommand(command)
{
    command := StrSplit(command, "（")[1]

    if (RegexMatch(command, "^(file|url)"))
    {
        cmd := StrSplit(command, " | ")[2]
        Run, %cmd%
    }
    else if (InStr(command, "function | ", true, 1))
    {
        cmd := StrSplit(command, " | ")[2]
        if (IsLabel(cmd))
        {
            GoSub, %cmd%
        }
    }
    else if (InStr(command, "cmd | ", true, 1))
    {
        cmd := StrSplit(command, " | ")[2]
        RunWithCmd(cmd)
    }
}

RunSelectedCommand1:
    index := Asc(SubStr(A_ThisHotkey, 3, 1)) - g_FirstChar + 1

    RunCommand(g_CurrentCommandList[index])
return

RunSelectedCommand2:
    ControlGetFocus, ctrl,
    if (ctrl == "Edit1")
    {
        return
    }

    index := Asc(SubStr(A_ThisHotkey, 2, 1)) - g_FirstChar + 1

    RunCommand(g_CurrentCommandList[index])
return

AddCustomCommand:
    ControlGetFocus, ctrl,
    if (ctrl == "Edit1")
    {
        return
    }

    index := Asc(SubStr(A_ThisHotkey, 3, 1)) - g_FirstChar + 1

    if (g_CurrentCommandList[index] != "")
    {
        g_Conf.AddKey("command", g_CurrentCommandList[index], g_CurrentInput)

        g_Conf.Save()

        LoadFiles()
    }
return

LoadFiles()
{
    g_Commands := Object()
    g_FallbackCommands := Object()

    for key, value in g_Conf.Command
    {
        if (value != "")
        {
            g_Commands.Insert(key . "（" . value "）")
        }
        else
        {
            g_Commands.Insert(key)
        }
    }

    userFunctionLabel := "UserFunctions"
    if (IsLabel(userFunctionLabel))
    {
        GoSub, %userFunctionLabel%
    }

    GoSub, Functions

    Loop, Read, %g_SearchFileList%
    {
        g_Commands.Insert(A_LoopReadLine)
    }
}

DisplayText(text)
{
    textToDisplay := StrReplace(text, "`n", "`r`n")
    ControlSetText, Edit2, %textToDisplay%
}

DisplayResult(result)
{
    DisplayText(result)
    g_UseDisplay := true
}

; AddAction(label, info, fallback)
@(label, info, fallback = false)
{
    g_Commands.Insert("function | " . label . "（" . info . "）")
    if (fallback)
    {
        g_FallbackCommands.Insert("function | " . label . "（" . info . "）")
    }
}

RunAndGetOutput(command)
{
    tempFileName := "RunZ.stdout.log"
    fullCommand = bash -c "%command% &> %tempFileName%"

    if (!FileExist("c:\msys64\usr\bin\bash.exe"))
    {
        fullCommand = %ComSpec% /C "%command% > %tempFileName%"
    }

    RunWait, %fullCommand%, %A_Temp%, Hide
    FileRead, result, %A_Temp%\%tempFileName%
    FileDelete, %A_Temp%\%tempFileName%
    return result
}

RunWithCmd(command)
{
    if (FileExist("c:\msys64\usr\bin\mintty.exe"))
    {
        Run, % "mintty -e sh -c '" command "; read'"
    }
    else
    {
        Run, % ComSpec " /C " command " & pause"
    }
}

OpenPath(filePath)
{
    if (!FileExist(filePath))
    {
        return
    }

    if (FileExist(g_Conf.Config.TCPath))
    {
        TCPath := g_Conf.Config.TCPath
        Run, %TCPath% /O /A /L="%filePath%"
    }
    else
    {
        SplitPath, filePath, , fileDir, ,
        Run, explorer "%fileDir%"
    }
}

OpenCurrentFileDir:
    filePath := StrSplit(g_CurrentCommand, " | ")[2]
    OpenPath(filePath)
return

DeleteCurrentFile:
    filePath := StrSplit(g_CurrentCommand, " | ")[2]

    if (!FileExist(filePath))
    {
        return
    }

    FileRecycle, % filePath
    GoSub, ReloadFiles
return

ShowCurrentFile:
    clipboard := StrSplit(g_CurrentCommand, " | ")[2]
    ToolTip, % clipboard
    SetTimer, RemoveToolTip, 800
return

RemoveToolTip:
    ToolTip
    SetTimer, RemoveToolTip, Off
return

#include %A_ScriptDir%\..\lib\class_EasyIni.ahk
#include %A_ScriptDir%\lib\Kanji\Kanji.ahk
#include %A_ScriptDir%\lib\TCMatch.ahk
#include %A_ScriptDir%\lib\Eval.ahk
#include %A_ScriptDir%\Functions.ahk
; 用户自定义命令
#include *i %A_ScriptDir%\UserFunctions.ahk

#NoEnv
#SingleInstance, Force
#NoTrayIcon

FileEncoding, utf-8
SendMode Input

; 自动生成的命令文件
global g_SearchFileList := A_ScriptDir . "\SearchFileList.txt"
; 配置文件
global g_ConfFile := A_ScriptDir . "\RunZ.ini"

if !FileExist(g_ConfFile)
{
    FileCopy, %g_ConfFile%.help.txt, %g_ConfFile%
}

global g_Conf := class_EasyINI(g_ConfFile)

; 所有命令
global g_Commands
; 当搜索无结果时使用的命令
global g_FallbackCommands
; 编辑框当前内容
global g_CurrentInput
; 当前匹配到的第一条命令
global g_CurrentCommand
; 当前匹配到的所有命令
global g_CurrentCommandList
; 是否启用 TCMatch
global g_EnableTCMatch = TCMatchOn(g_Conf.Config.TCMatchPath)
; 列表第一列的首字母或数字
global g_FirstChar := Asc(g_Conf.Gui.FirstChar)
; 在列表中显示的行数
global g_DisplayRows := g_Conf.Gui.DisplayRows
; 在列表中显示的文字列数（多出的会被截断）
global g_DisplayCols := g_Conf.Gui.DisplayCols
; 命令使用了显示框
global g_UseDisplay
; 当前输入命令的参数，数组，为了方便没有添加 g_ 前缀
global Arg

if (FileExist(g_SearchFileList))
{
    LoadFiles()
}
else
{
    GoSub, ReloadFiles
}

Gui, Main:Font, % "s" g_Conf.Gui.FontSize, % g_Conf.Gui.FontName
Gui, Main:Add, Edit, % "gProcessInputCommand vSearchArea"
        . " w" g_Conf.Gui.WidgetWidth " h" g_Conf.Gui.EditHeight,
Gui, Main:Add, Edit, % "ReadOnly vDisplayArea"
        . " w" g_Conf.Gui.WidgetWidth " h" g_Conf.Gui.DisplayAreaHeight
        , % SearchCommand("", true)
if (g_Conf.Gui.ShowCurrentCommand)
{
    Gui, Main:Add, Edit, % "ReadOnly"
        . " w" g_Conf.Gui.WidgetWidth " h" g_Conf.Gui.EditHeight,
}
Gui, Main:Show, , RunZ
if (g_Conf.Gui.HideTitle)
{
    WinSet, Style, -0xC00000, A
}

Hotkey, IfWinActive, RunZ
Hotkey, ~enter, RunCurrentCommand
Hotkey, ^j, ClearInput
Hotkey, f1, Help
Hotkey, f2, EditConfig
Hotkey, esc, ExitRunZ
Hotkey, ^d, OpenCurrentFileDir
Hotkey, ^x, DeleteCurrentFile
Hotkey, ^s, ShowCurrentFile
Hotkey, ^r, ReloadFiles

if (g_Conf.Config.RunInBackground)
{
    Hotkey, esc, WindowMin
}

Loop, % g_DisplayRows
{
    key := Chr(g_FirstChar + A_Index - 1)
    ; lalt +
    Hotkey, <!%key%, RunSelectedCommand1
    ; tab +
    Hotkey, ~%key%, RunSelectedCommand2
    ; shift +
    Hotkey, ~+%key%, AddCustomCommand
}

if (g_Conf.Config.SaveInputText && g_Conf.Auto.InputText != "")
{
    Send, % g_Conf.Auto.InputText
}

return

ExitRunZ:
    if (g_Conf.Config.SaveInputText)
    {
        g_Conf.DeleteKey("auto", "InputText")
        g_Conf.AddKey("auto", "InputText", g_CurrentInput)
        g_Conf.Save()
    }

    ExitApp
return

WindowMin:
    WinMinimize, A
return

GenerateSearchFileList()
{
    FileDelete, %g_SearchFileList%

    searchFileType := g_Conf.Config.SearchFileType

    for dirIndex, dir in StrSplit(g_Conf.Config.SearchFileDir, " | ")
    {
        if (InStr(dir, "A_") == 1)
        {
            searchPath := %dir%
        }
        else
        {
            searchPath := dir
        }

        for extIndex, ext in StrSplit(searchFileType, " | ")
        {
            Loop, Files, %searchPath%\%ext%, R
            {
                if (g_Conf.Config.SearchFileExclude != ""
                        && RegexMatch(A_LoopFileLongPath, g_Conf.Config.SearchFileExclude))
                {
                    continue
                }
                FileAppend, file | %A_LoopFileLongPath%`n, %g_SearchFileList%,
            }
        }
    }
}

ReloadFiles:
    GenerateSearchFileList()

    LoadFiles()
return

ProcessInputCommand:
    GuiControlGet, g_CurrentInput, , SearchArea
    SearchCommand(g_CurrentInput)
return

SearchCommand(command = "", firstRun = false)
{
    result := ""
    commandPrefix := SubStr(command, 1, 1)

    if (commandPrefix ==  ";" || commandPrefix == ":")
    {
        if (commandPrefix == ";")
        {
            g_CurrentCommand := g_FallbackCommands[1]
        }
        else if (commandPrefix == ":")
        {
            g_CurrentCommand := g_FallbackCommands[2]
        }

        g_CurrentCommandList.Insert(g_CurrentCommand)
        result .= "a | " . g_CurrentCommand
        Arg := SubStr(g_CurrentInput, 2)
        DisplaySearchResult(result)
        return result
    }
    ; 用空格来判断参数
    else if (InStr(command, " ") && g_CurrentCommand != "")
    {
        Arg := SubStr(command, InStr(command, " ") + 1)
        return
    }

    g_CurrentCommandList := Object()

    order := g_FirstChar

    for index, element in g_Commands
    {
        elementToSearch := StrSplit(element, " | ")[2]

        if (InStr(element, "file | ", true, 1))
        {
            ; 只搜不带扩展名的文件名
            SplitPath, elementToSearch, , fileDir, , fileNameNoExt
            elementToShow := SubStr("file | " . fileNameNoExt, 1, g_DisplayCols)

            if (g_Conf.Config.SearchFullPath)
            {
                ; TCMatch 在搜索路径时只搜索文件名，强行将 \ 转成空格
                elementToSearch := StrReplace(fileDir . "\" . fileNameNoExt, "\", " ")
            }
        }
        else
        {
            elementToShow := SubStr(element, 1, g_DisplayCols)
        }

        if (MatchCommand(elementToSearch, command))
        {
            g_CurrentCommandList.Insert(element)

            if (order == g_FirstChar)
            {
                g_CurrentCommand := element
            }
            else
            {
                result .= "`n"
            }

            result .= Chr(order++) . " | " . elementToShow

            if (order - g_FirstChar >= g_DisplayRows)
            {
                break
            }
            ; 第一次运行只加载 function 类型
            if (firstRun && (order - g_FirstChar >= g_DisplayRows - 4))
            {
                result .= "`n`n现有 " g_Commands.Length() " 条命令。"
                result .= "`n`n键入内容 搜索，回车 执行第一条，Alt + 字母 执行，F1 帮助，Esc 退出。"

                break
            }
        }
    }

    if (result == "")
    {
        g_CurrentCommand := g_FallbackCommands[1]
        g_CurrentCommandList := g_FallbackCommands
        Arg := g_CurrentInput

        for index, element in g_FallbackCommands
        {
            if (index != 1)
            {
                result .= "`n"
            }

            result .= Chr(g_FirstChar - 1 + index++) . " | " . element
        }
    }

    DisplaySearchResult(result)
    return result
}

DisplaySearchResult(result)
{
    DisplayText(result)

    if (g_CurrentCommandList.Length() == 1 && g_Conf.Config.RunIfOnlyOne)
    {
        GoSub, RunCurrentCommand
    }

    if (g_Conf.Gui.ShowCurrentCommand)
    {
        ControlSetText, Edit3, %g_CurrentCommand%
    }
}

ClearInput:
    ControlSetText, Edit1,
return

RunCurrentCommand:
    if (g_CurrentInput != "")
    {
        g_UseDisplay := false

        RunCommand(g_CurrentCommand)
        if (g_Conf.Config.RunOnce && !g_UseDisplay)
        {
            GoSub, ExitRunZ
        }
    }
return

MatchCommand(Haystack, Needle)
{
    if (g_EnableTCMatch)
    {
        return TCMatch(Haystack, Needle)
    }

    return InStr(Haystack, Needle)
}

RunCommand(command)
{
    command := StrSplit(command, "（")[1]

    if (RegexMatch(command, "^(file|url)"))
    {
        cmd := StrSplit(command, " | ")[2]
        Run, %cmd%
    }
    else if (InStr(command, "function | ", true, 1))
    {
        cmd := StrSplit(command, " | ")[2]
        if (IsLabel(cmd))
        {
            GoSub, %cmd%
        }
    }
    else if (InStr(command, "cmd | ", true, 1))
    {
        cmd := StrSplit(command, " | ")[2]
        RunWithCmd(cmd)
    }
}

RunSelectedCommand1:
    index := Asc(SubStr(A_ThisHotkey, 3, 1)) - g_FirstChar + 1

    RunCommand(g_CurrentCommandList[index])
return

RunSelectedCommand2:
    ControlGetFocus, ctrl,
    if (ctrl == "Edit1")
    {
        return
    }

    index := Asc(SubStr(A_ThisHotkey, 2, 1)) - g_FirstChar + 1

    RunCommand(g_CurrentCommandList[index])
return

AddCustomCommand:
    ControlGetFocus, ctrl,
    if (ctrl == "Edit1")
    {
        return
    }

    index := Asc(SubStr(A_ThisHotkey, 3, 1)) - g_FirstChar + 1

    if (g_CurrentCommandList[index] != "")
    {
        g_Conf.AddKey("command", g_CurrentCommandList[index], g_CurrentInput)

        g_Conf.Save()

        LoadFiles()
    }
return

LoadFiles()
{
    g_Commands := Object()
    g_FallbackCommands := Object()

    for key, value in g_Conf.Command
    {
        if (value != "")
        {
            g_Commands.Insert(key . "（" . value "）")
        }
        else
        {
            g_Commands.Insert(key)
        }
    }

    userFunctionLabel := "UserFunctions"
    if (IsLabel(userFunctionLabel))
    {
        GoSub, %userFunctionLabel%
    }

    GoSub, Functions

    Loop, Read, %g_SearchFileList%
    {
        g_Commands.Insert(A_LoopReadLine)
    }
}

DisplayText(text)
{
    textToDisplay := StrReplace(text, "`n", "`r`n")
    ControlSetText, Edit2, %textToDisplay%
}

DisplayResult(result)
{
    DisplayText(result)
    g_UseDisplay := true
}

; AddAction(label, info, fallback)
@(label, info, fallback = false)
{
    g_Commands.Insert("function | " . label . "（" . info . "）")
    if (fallback)
    {
        g_FallbackCommands.Insert("function | " . label . "（" . info . "）")
    }
}

RunAndGetOutput(command)
{
    tempFileName := "RunZ.stdout.log"
    fullCommand = bash -c "%command% &> %tempFileName%"

    if (!FileExist("c:\msys64\usr\bin\bash.exe"))
    {
        fullCommand = %ComSpec% /C "%command% > %tempFileName%"
    }

    RunWait, %fullCommand%, %A_Temp%, Hide
    FileRead, result, %A_Temp%\%tempFileName%
    FileDelete, %A_Temp%\%tempFileName%
    return result
}

RunWithCmd(command)
{
    if (FileExist("c:\msys64\usr\bin\mintty.exe"))
    {
        Run, % "mintty -e sh -c '" command "; read'"
    }
    else
    {
        Run, % ComSpec " /C " command " & pause"
    }
}

OpenPath(filePath)
{
    if (!FileExist(filePath))
    {
        return
    }

    if (FileExist(g_Conf.Config.TCPath))
    {
        TCPath := g_Conf.Config.TCPath
        Run, %TCPath% /O /A /L="%filePath%"
    }
    else
    {
        SplitPath, filePath, , fileDir, ,
        Run, explorer "%fileDir%"
    }
}

OpenCurrentFileDir:
    filePath := StrSplit(g_CurrentCommand, " | ")[2]
    OpenPath(filePath)
return

DeleteCurrentFile:
    filePath := StrSplit(g_CurrentCommand, " | ")[2]

    if (!FileExist(filePath))
    {
        return
    }

    FileRecycle, % filePath
    GoSub, ReloadFiles
return

ShowCurrentFile:
    clipboard := StrSplit(g_CurrentCommand, " | ")[2]
    ToolTip, % clipboard
    SetTimer, RemoveToolTip, 800
return

RemoveToolTip:
    ToolTip
    SetTimer, RemoveToolTip, Off
return

#include %A_ScriptDir%\..\lib\class_EasyIni.ahk
#include %A_ScriptDir%\lib\Kanji\Kanji.ahk
#include %A_ScriptDir%\lib\TCMatch.ahk
#include %A_ScriptDir%\lib\Eval.ahk
#include %A_ScriptDir%\Functions.ahk
; 用户自定义命令
#include *i %A_ScriptDir%\UserFunctions.ahk


[feature] Global printscreen to apps key mapping

; Autohotkey configuration file
; AHK Version v.1.1.32.00
; Franklin Chou (franklin.chou@nelsonmullins.com)
; 2 May 2020
; Tested to work on Lenovo X1 Yoga, Gen. 4

#Persistent

CapsLock::Ctrl
LCtrl::Return
; LCtrl::CapsLock
PrintScreen::AppsKey

; SYSTEM ----------------------------------------------------------------------

; Access different windows of the same group
!`::
  WinGet, process_name, ProcessName, A ; get the active window's process name
  process_windows := GetWindowsOfProcess(process_name)

  n_process_windows := process_windows.Length()

  index := 1 ; AHK arrays are 1 indexed
  While(GetKeyState("Alt", "P")) {
    If (GetKeyState("``", "P")) {
      If (index < n_process_windows) {
        index := index + 1
      } Else {
        index := 1
      }
      active_id := process_windows[index]
      WinActivate, ahk_id %active_id%
    }
  }
  index := ""
  process_windows := ""
  n_process_windows := ""
Return

; Get the window ids of all the processes under that process name
GetWindowsOfProcess(process_name) {
  ids := Array()
  WinGet, window_ids, List ; get the IDs for all running windows
  Loop %window_ids% {
    id := window_ids%A_Index%
    WinGetTitle, title, ahk_id %id%
    WinGet, a_process_name, ProcessName, ahk_id %id%
    ; only include windows with visible title
    If (title && a_process_name = process_name) {
      ids.Push(id)
    }
  }
  Return, ids
}

; utility to get selected text (if any)
GetSelectedText() {
  temp := ClipboardAll
  Clipboard := ""
  Send ^c
  ClipWait, 0, 1
  selection := Clipboard
  Clipboard := temp
  Return, selection
}

; TIMEKEEPER ------------------------------------------------------------------

; Shift focus to the timekeeper app
#!e::
  timekeeper_app := WinExist("ahk_class WindowsForms10.Window.8.app.0.262fb3d")
  If(timekeeper_app > 0) {
    WinActivate, ahk_id %timekeeper_app%
  } Else {
    Run, DTE.exe, C:\Program Files (x86)\DTEAxiom
  }
Return

; Start the timer on the selected item in the daily view
#IfWinActive ahk_class WindowsForms10.Window.8.app.0.262fb3d
  >+s::
    WinGetActiveTitle, active_title
    selected := GetSelectedText()
    is_releasable := RegExMatch(selected, "Ready to be released|Timer still running")
    ; match weekly view, 1 application window
    If (is_releasable && RegExMatch(active_title, "DTE Axiom") > 0) {
      WinMove, 0, 0
      MouseMove, 100, 460
      DTEAppContextClick(4, 460)
    ; match monthly view, 2 application windows
    ; in this view, Ctrl + C does NOT copy the selected text
    ; so `is_releasable` is useless
    } Else If(RegExMatch(active_title, "^Entries for") > 0) {
      WinMove, 0, 0
      ; when figuring out how low to get the mouse to move aim for the area
      ; of the menu bar that says "Drag a column header here..."
      MouseMove, 100, 280
      DTEAppContextClick(4, 280)
    } Else {
      MsgBox Select releasable entry
      Return
    }
    is_releasable := ""
    selected := ""
Return

; click the item in the DTE context menu that is `item_position` from the top
; with the starting position of `initial_mouse` (y-axis offset)
DTEAppContextClick(item_position, initial_mouse) {
    ; each item in the dropdown is approximately 25 pixels
    drop_down := 25
    Send {RButton}
    Sleep, 10 ; sleep to allow submenu time to come up
    MouseMove, 170, (initial_mouse + 20) + drop_down * item_position
    Send {LButton}
}

; MSOFFICE --------------------------------------------------------------------

; Outlook

#If WinActive("ahk_class rctrl_renwnd32")
  ; disable Ctrl + D as delete email
  ^d::Return

  ; disable Ctrl + E as find
  $^e::Return

  ; remap Ctrl + F to find
  ^f::
    WinGetActiveTitle, title
    ; IN MESSAGE, Ctrl + F maps to F4
    If (RegExMatch(title, " - Message") > 0) {
      Send {F4}
    } Else {
      Send ^e
    }
    title := ""
Return

; This ridiculous keymapping is care of Lenovo
; which maps F12 to some bloatware keyboard manager utility
#If WinActive("ahk_class OpusApp") || WinActive("ahk_class XLMAIN")
  F12::Send {F12}
Return

; WORD ONLY -------------------------------------------------------------------

; Cycle through types of markup
#If WinActive("ahk_class OpusApp")
  >+m::
    Send !r
    Sleep, 10
    Send td
    Send {Down}
    Send {Enter}
Return

; Bring up the tab stop modification dialogue
#If WinActive("ahk_class OpusApp")
  >+t::
    Send !h
    Send pg
    Send !t
Return

; Autohotkey configuration file
; AHK Version v.1.1.32.00
; Franklin Chou (franklin.chou@nelsonmullins.com)
; 2 May 2020
; Tested to work on Lenovo X1 Yoga, Gen. 4

#Persistent

CapsLock::Ctrl
LCtrl::Return
; LCtrl::CapsLock

; SYSTEM ----------------------------------------------------------------------

; Access different windows of the same group
!`::
  WinGet, process_name, ProcessName, A ; get the active window's process name
  process_windows := GetWindowsOfProcess(process_name)

  n_process_windows := process_windows.Length()

  index := 1 ; AHK arrays are 1 indexed
  While(GetKeyState("Alt", "P")) {
    If (GetKeyState("``", "P")) {
      If (index < n_process_windows) {
        index := index + 1
      } Else {
        index := 1
      }
      active_id := process_windows[index]
      WinActivate, ahk_id %active_id%
    }
  }
  index := ""
  process_windows := ""
  n_process_windows := ""
Return

; Get the window ids of all the processes under that process name
GetWindowsOfProcess(process_name) {
  ids := Array()
  WinGet, window_ids, List ; get the IDs for all running windows
  Loop %window_ids% {
    id := window_ids%A_Index%
    WinGetTitle, title, ahk_id %id%
    WinGet, a_process_name, ProcessName, ahk_id %id%
    ; only include windows with visible title
    If (title && a_process_name = process_name) {
      ids.Push(id)
    }
  }
  Return, ids
}

; utility to get selected text (if any)
GetSelectedText() {
  temp := ClipboardAll
  Clipboard := ""
  Send ^c
  ClipWait, 0, 1
  selection := Clipboard
  Clipboard := temp
  Return, selection
}

; TIMEKEEPER ------------------------------------------------------------------

; Shift focus to the timekeeper app
#!e::
  timekeeper_app := WinExist("ahk_class WindowsForms10.Window.8.app.0.262fb3d")
  If(timekeeper_app > 0) {
    WinActivate, ahk_id %timekeeper_app%
  } Else {
    Run, DTE.exe, C:\Program Files (x86)\DTEAxiom
  }
Return

; Start the timer on the selected item in the daily view
#IfWinActive ahk_class WindowsForms10.Window.8.app.0.262fb3d
  >+s::
    WinGetActiveTitle, active_title
    selected := GetSelectedText()
    is_releasable := RegExMatch(selected, "Ready to be released|Timer still running")
    ; match weekly view, 1 application window
    If (is_releasable && RegExMatch(active_title, "DTE Axiom") > 0) {
      WinMove, 0, 0
      MouseMove, 100, 460
      DTEAppContextClick(4, 460)
    ; match monthly view, 2 application windows
    ; in this view, Ctrl + C does NOT copy the selected text
    ; so `is_releasable` is useless
    } Else If(RegExMatch(active_title, "^Entries for") > 0) {
      WinMove, 0, 0
      ; when figuring out how low to get the mouse to move aim for the area
      ; of the menu bar that says "Drag a column header here..."
      MouseMove, 100, 280
      DTEAppContextClick(4, 280)
    } Else {
      MsgBox Select releasable entry
      Return
    }
    is_releasable := ""
    selected := ""
Return

; click the item in the DTE context menu that is `item_position` from the top
; with the starting position of `initial_mouse` (y-axis offset)
DTEAppContextClick(item_position, initial_mouse) {
    ; each item in the dropdown is approximately 25 pixels
    drop_down := 25
    Send {RButton}
    Sleep, 10 ; sleep to allow submenu time to come up
    MouseMove, 170, (initial_mouse + 20) + drop_down * item_position
    Send {LButton}
}

; MSOFFICE --------------------------------------------------------------------

; Let the print screen key open the application options key (for spell check)
; Word and Outlook
#If WinActive("ahk_class OpusApp") || WinActive("ahk_class rctrl_renwnd32")
  PrintScreen::AppsKey
Return

; Outlook

#If WinActive("ahk_class rctrl_renwnd32")
  ; disable Ctrl + D as delete email
  ^d::Return

  ; disable Ctrl + E as find
  $^e::Return

  ; remap Ctrl + F to find
  ^f::
    WinGetActiveTitle, title
    ; IN MESSAGE, Ctrl + F maps to F4
    If (RegExMatch(title, " - Message") > 0) {
      Send {F4}
    } Else {
      Send ^e
    }
    title := ""
Return

; This ridiculous keymapping is care of Lenovo
; which maps F12 to some bloatware keyboard manager utility
#If WinActive("ahk_class OpusApp") || WinActive("ahk_class XLMAIN")
  F12::Send {F12}
Return

; WORD ONLY -------------------------------------------------------------------

; Cycle through types of markup
#If WinActive("ahk_class OpusApp")
  >+m::
    Send !r
    Sleep, 10
    Send td
    Send {Down}
    Send {Enter}
Return

; Bring up the tab stop modification dialogue
#If WinActive("ahk_class OpusApp")
  >+t::
    Send !h
    Send pg
    Send !t
Return


DC 插件：创建新文件窗口，只选定扩展名之外的文件名

DC 插件：创建新文件窗口，只选定扩展名之外的文件名

/*
    此插件仅供自用，依赖对 DC 代码的修改以及专门的配置

    ---

    DC 的优势

    开源，免费，跨平台，可以自由改代码定制功能，很好编译
    可以改代码让所有目录中的父目录（..）消失（已完成）
    可以把按键绑定到工具栏的子菜单上，然后再通过按键触发功能
    内建 lua 解释器，方便写一些高级功能（感觉功能有限，用处不大）
    主界面和配置界面更漂亮、好用
*/

DoubleCommander:
    global DC_Class := "TTOTAL_CMD"
    global DC := "ahk_class " . DC_Class
    global DC_Dir := "c:\mine\app\doublecmd"
    global DC_Path := "c:\mine\app\doublecmd\doublecmd.exe --no-splash"
    ; 用于记录文件打开对话框所属窗体
    global DC_CallerId := 0

    DC_Name := "DoubleCommander"

    Vim.SetWin(DC_Name, DC_Class, "doublecmd.exe")
    Vim.Mode("normal", DC_Name)

    Vim.BeforeActionDo("DC_ForceInsertMode", DC_Name)
return

DC_ForceInsertMode() {
    ControlGetFocus, Ctrl
    if (InStr(Ctrl, "Edit") == 1) {
        return true
    }

    WinGet, MenuID, ID, AHK_CLASS #32768
    if (MenuID != "") {
        return true
    }

    return false
}

DC_Run(Cmd) {
    ControlSetText, Edit1, % Cmd, % DC
    ControlSend, Edit1, {Enter}, % DC
}

; 返回值 [1]: left/right [2]: 左侧面板所占比例 0-100
DC_GetPanelInfo() {
    ClipSaved := ClipboardAll
    Clipboard := ""
    DC_Run("cm_CopyPanelInfoToClip")
    ClipWait, 1

    PanelInfo := StrSplit(Clipboard, " ")
    Clipboard := ClipSaved

    return PanelInfo
}

DC_ExecuteToolbarItem(ID) {
    DC_Run("cm_ExecuteToolbarItem ToolItemID=" . ID)
}

DC_ColumnsView(ColumnSet) {
    if (ColumnSet == "") {
        DC_Run("cm_ColumnsView")
    } else {
        DC_Run("cm_ColumnsView columnset=" . ColumnSet)
    }
}

DC_OpenPath(Path, InNewTab := true, LeftOrRight := "") {
    LeftOfRight := DC_GetPanelInfo()[1]
    if (LeftOfRight == "right") {
        LeftOrRight := "-R"
    } else {
        LeftOrRight := "-L"
    }

    if (InNewTab) {
        Run, %DC_Path% -C -T "%LeftOrRight%" "%Path%"
    } else {
        Run, %DC_Path% -C "%LeftOrRight%" "%Path%"
    }
}

; funcend

<DC_Test>:
    ; DC_ExecuteToolbarItem("{700FF494-B939-48A3-B248-8823EB366AEA}")
    DC_Run("cm_About")
return

<DC_Restart>:
    WinClose, % DC
    WinWaitClose, % DC, , 2

    Run, % DC_Path

    WinWaitActive, % DC

    if (!WinExist(DC)) {
        MsgBox, 重启失败 %ErrorMessage%
    }
return

<DC_Show_50_50>:
    DC_Run("cm_PanelsSplitterPerPos splitpct=50")
return

<DC_Show_100_0>:
    DC_Run("cm_PanelsSplitterPerPos splitpct=100")
return

<DC_Show_0_100>:
    DC_Run("cm_PanelsSplitterPerPos splitpct=0")
return

<DC_HorizontalFilePanels>:
    DC_Run("cm_HorizontalFilePanels mode=legacy")
return

<DC_Toggle_50_100>:
    PanelInfo := DC_GetPanelInfo()

    if (Abs(50 - PanelInfo[2]) < 10) {
        if (PanelInfo[1] == "left") {
            DC_Run("cm_PanelsSplitterPerPos splitpct=100")
        } else {
            DC_Run("cm_PanelsSplitterPerPos splitpct=0")
        }
    } else {
        DC_Run("cm_PanelsSplitterPerPos splitpct=50")
    }
return

<DC_MakeDir>:
    DC_Run("cm_MakeDir")
return

<DC_PreviousParallelDir>:
    SleepTime := 10

    ClipSaved := ClipboardAll
    Clipboard := ""
    DC_Run("cm_CopyCurrentPathToClip")
    ClipWait, 1

    OldPwd := Clipboard

    if (InStr(OldPwd, "\") == 1) {
        ; 网络文件系统比较慢
        SleepTime := 50
    }

    if (StrLen(OldPwd) == 3) {
        ; 在根分区

        Clipboard := ClipSaved
        ClipSaved := ""

        return
    }

    DC_Run("cm_ChangeDirToParent")
    Sleep, % SleepTime

    DC_Run("cm_GoToPrevEntry")
    Sleep, % SleepTime

    Send, {Right}

    Clipboard := ClipSaved
    ClipSaved := ""
return

<DC_NextParallelDir>:
    SleepTime := 10

    ClipSaved := ClipboardAll
    Clipboard := ""
    DC_Run("cm_CopyCurrentPathToClip")
    ClipWait, 1

    OldPwd := Clipboard

    if (InStr(OldPwd, "\") == 1) {
        ; 网络文件系统比较慢
        SleepTime := 50
    }

    if (StrLen(OldPwd) == 3) {
        ; 在根分区
        ; Gosub, <cm_GotoPreviousDrive>

        Clipboard := ClipSaved
        ClipSaved := ""

        return
    }

    DC_Run("cm_ChangeDirToParent")
    Sleep, % SleepTime

    DC_Run("cm_GoToNextEntry")
    Sleep, % SleepTime

    Send, {Right}
    Sleep, % SleepTime

    Clipboard := ""
    DC_Run("cm_CopyCurrentPathToClip")
    ClipWait, 1

    if (OldPwd != Clipboard && InStr(OldPwd, Clipboard) == 1) {
        ; 下一个是文件
        DC_Run("cm_ViewHistoryPrev")
    }

    Clipboard := ClipSaved
    ClipSaved := ""
return

<DC_CreateNewFile>:
    ControlGetFocus, TLB, % DC
    ControlGetPos, Xn, Yn, , , % TLB, % DC

    Menu, NewFileMenu, Add
    Menu, NewFileMenu, DeleteAll
    Menu, NewFileMenu, Add , S >> 快捷方式, <DC_CreateFileShortcut>
    Menu, NewFileMenu, Icon, S >> 快捷方式, %A_WinDir%\system32\Shell32.dll, 264
    Menu, NewFileMenu, Add

    Loop, % DC_Dir . "\shellnew\*.*" {
        Ft := SubStr(A_LoopFileName, 1, 1) . " >> " . A_LoopFileName
        Menu, NewFileMenu, Add, % Ft, DC_NewFileMenuAction
        Menu, NewFileMenu, Icon, % Ft, %A_WinDir%\system32\Shell32.dll
    }

    Menu, NewFileMenu, Show, % Xn, % Yn + 2
return

DC_NewFileMenuAction:
    Filename := RegExReplace(A_ThisMenuItem, ".\s>>\s")
    FilePath := DC_Dir . "\ShellNew\" . Filename

    Gui, Destroy
    Gui, Add, Text, x12 y20 w50 h20 +Center, 模板源
    Gui, Add, Edit, x72 y20 w300 h20 Disabled, % FilePath
    Gui, Add, Text, x12 y50 w50 h20 +Center, 新建文件
    Gui, Add, Edit, x72 y50 w300 h20, % Filename
    Gui, Add, Button, x162 y80 w90 h30 gDC_NewFileOk default, 确认(&S)
    Gui, Add, Button, x282 y80 w90 h30 gDC_NewFileClose , 取消(&C)
    Gui, Show, w400 h120, 新建文件

    if (InStr(Filename, ".")) {
        ; 只选定扩展名之外的文件名
        PostMessage, 0x0B1, 0, % InStr(Filename, ".") - 1, Edit2, A
    }
return

DC_NewFileClose:
    Gui, Destroy
return

DC_NewFileOK:
    GuiControlGet, SrcFilePath, , Edit1
    GuiControlGet, NewFilename, , Edit2

    ClipSaved := ClipboardAll
    Clipboard :=
    DC_Run("cm_CopyCurrentPathToClip")
    ClipWait, 1
    DstPath := Clipboard
    Clipboard := ClipSaved
    ClipSaved := ""

    if (InStr(DstPath, "`r")) {
        DstPath := SubStr(DstPath, 1, InStr(DstPath, "`r") - 1)
    } else if (DstPath == "") {
        return
    }

    NewFilePath := DstPath . NewFilename
    if (FileExist(NewFilePath)) {
        MsgBox, 4, 新建文件, 新建文件已存在，是否覆盖？
        IfMsgBox No
            return
    }

    FileCopy, % SrcFilePath, % NewFilePath, 1

    ; 虽然不是完全匹配，基本也能用了
    DC_Run("cm_QuickSearch matchbeginning=on | text=" . NewFilename)

    Gui, Destroy
return

<DC_Toggle>:
    if (WinExist(DC)) {
        WinGet, Ac, MinMax, % DC
        if (Ac == -1) {
            WinActivate, % DC
        } else {
            if (!WinActive(DC)) {
                WinActivate, % DC
            } else {
                WinMinimize, % DC
            }
        }
    } else {
        Run, % DC_Path
        WinWait, % DC

        if (!WinActive(DC)) {
            WinActivate, % DC
        }
    }
return

<DC_SortByName>:
    DC_Run("cm_SortByName")
return

<DC_SortByExt>:
    DC_Run("cm_SortByExt")
return

<DC_SortBySize>:
    DC_Run("cm_SortBySize")
return

<DC_SortByDate>:
    DC_Run("cm_SortByDate")
return

<DC_SortByAttr>:
    DC_Run("cm_SortByAttr")
return

<DC_ReverseOrder>:
    DC_Run("cm_ReverseOrder")
return

<DC_FocusSwap>:
    DC_Run("cm_FocusSwap")
    ; side=left/right
return

<DC_CopyCurrentPathToClip>:
    DC_Run("cm_CopyCurrentPathToClip")
return

<DC_OpenExplorer>:
    DC_Run(".")
return

<DC_MarkFile>:
    DC_Run("cm_EditComment")
    ; 不要在已有备注的文件使用
    Send, ^+{End}🖥{F2}
return

<DC_UnMarkFile>:
    DC_Run("cm_EditComment")
    ; 删除 DC_MarkFile 的文件标记，也可用于清空文件备注
    Send, ^+{End}{Del}{F2}
return

<DC_ShowMainMenu>:
    DC_Run("cm_ShowMainMenu")
return

<DC_ShowButtonMenu>:
    DC_Run("cm_ShowButtonMenu")
return

<DC_OperationsViewer>:
    DC_Run("cm_OperationsViewer")
return

<DC_TreeView>:
    DC_Run("cm_TreeView")
return

<DC_FocusTreeView>:
    DC_Run("cm_FocusTreeView")
return

<DC_BriefView>:
    DC_Run("cm_BriefView")
return

<DC_ColumnsView1>:
    DC_ColumnsView("mine")
return

<DC_ColumnsView2>:
    DC_ColumnsView("test")
return

<DC_ThumbnailsView>:
    DC_Run("cm_ThumbnailsView")
    Gosub, <DC_ThumbnailsSwitchKey>
return

<DC_ThumbnailsSwitchKey>:
    InThumbsView := !InThumbsView

    if (InThumbsView) {
        Vim.Map("l", "<right>", DC_Name)
    } else {
        Vim.Map("l", "<enter>", DC_Name)
    }
return

<DC_ToggleShowInfo>:
    Vim.GetWin(DC_Name).SetInfo(!Vim.GetWin(DC_Name).info)
return

<DC_CopyFileContent>:
    Clipboard := ""
    DC_Run("cm_CopyFullNamesToClip")
    ClipWait, 1

    Fileread, Contents, % Clipboard
    Clipboard := Contents
return

<DC_CopyFilenamesOnly>:
    Clipboard := ""
    DC_Run("cm_CopyFullNamesToClip")
    ClipWait, 1

    SplitPath, Clipboard, OutFileName, , , OutFilenameNoExt

    if (InStr(FileExist(Clipboard), "D")) {
        Clipboard := OutFileName
    } else if (InStr(Clipboard, ".")) {
        Clipboard := OutFilenameNoExt
    }
return

<DC_CreateFileShortcut>:
    ClipSaved := ClipboardAll
    Clipboard := ""
    DC_Run("cm_CopyFullNamesToClip")
    ClipWait

    FilePath := Clipboard
    Clipboard := ClipSaved
    ClipSaved := ""

    OutVar := FileExist(FilePath)
    if (InStr(OutVar, "D")) {
        FileCreateShortcut, % FilePath, % FilePath . ".lnk"
    } else if (OutVar != "") {
        FileCreateShortcut, % FilePath, % RegExReplace(FilePath, "\.[^.]*$", ".lnk")
    }
return

<DC_Focus>:
    IfWinExist, % DC
        Winactivate, % DC
    else {
        Run, % DC_Path
        WinWait, % DC
        IfWinNotActive, % DC
            WinActivate, % DC
    }
return

<DC_MapKeys>:
	Vim.Mode("normal", DC_Name)
    Vim.Map("<S-Enter>", "<DC_SelectedCurrentDir>", DC_Name)
    Vim.Map("<Esc>", "<DC_ReturnToCaller>", DC_Name)
return

<DC_UnMapKeys>:
	Vim.Mode("normal", DC_Name)
    Vim.Map("<S-Enter>", "<Default>", DC_Name)
    Vim.Map("<Esc>", "<Default>", DC_Name)
return

; 返回调用者
<DC_ReturnToCaller>:
    gosub <DC_UnMapKeys>

    WinActivate, ahk_id %DC_CallerId%

    DC_CallerId := 0
return

; 非 TC 窗口按下后激活 TC 窗口
; TC 窗口按下后复制当前选中文件返回原窗口后粘贴
<DC_OpenDCDialog>:
    WinGetClass, name, A

    ; 在 DC 按下快捷键时，激活调用窗体并执行粘贴操作
    if (name == DC_Class) {
        if (DC_CallerId != 0) {
            gosub <DC_Selected>
            DC_CallerId := 0
		}
    } else {
        DC_CallerId := WinExist("A")
        if (DC_CallerId == 0) {
            return
		}

        gosub <DC_Focus>
        gosub <DC_MapKeys>
    }
return

<DC_Selected>:
    gosub <DC_UnMapKeys>

    Clipboard := ""
    ; 不知道什么原因，必须加一个 MsgBox 功能才正常
    MsgBox, , , 处理中, 0.3

    DC_Run("cm_CopyCurrentPathToClip")

    ClipWait, 1
    Pwd := Clipboard

    Clipboard := ""
    DC_Run("cm_CopyNamesToClip")
    ClipWait, 1

    WinActivate, ahk_id %DC_CallerId%
    WinWait, ahk_id %DC_CallerId%
    DC_CallerId := 0

    if (!InStr(Clipboard, "`n")) {
        Clipboard := Pwd . Clipboard
        Send, {Home}
        Send, ^v
        Send, {Enter}

        return
    }

    ; 多选

    Files := ""
    Loop, parse, Clipboard, `n, `r
        Files .= """" . A_LoopField  . """ "

    ; 第一步：跳转到当前路径
    Clipboard := Pwd
    Send, ^a
    Send, ^v
    Send, {Enter}
    sleep, 100

    ; 第二步：提交文件名
    Clipboard := Files
    Send, ^v
    Send, {Enter}
return

<DC_SelectedCurrentDir>:
    gosub <DC_UnMapKeys>

    if (DC_CallerId == 0) {
        return
    }

    Clipboard := ""
    DC_Run("cm_CopyCurrentPathToClip")
    ClipWait

    ; 添加默认路径不带反斜杠，添加之

    Clipboard .= "\"

    WinActivate, ahk_id %DC_CallerId%
    WinWait, ahk_id %DC_CallerId%
    DC_CallerId := 0

    Send, {Home}
    Send, ^v
    Send, {Enter}
return

<DC_FlatViewSel>:
    DC_Run("cm_FlatViewSel")
return

/*
    此插件仅供自用，依赖对 DC 代码的修改以及专门的配置

    ---

    DC 的优势

    开源，免费，跨平台，可以自由改代码定制功能，很好编译
    可以改代码让所有目录中的父目录（..）消失（已完成）
    可以把按键绑定到工具栏的子菜单上，然后再通过按键触发功能
    内建 lua 解释器，方便写一些高级功能（感觉功能有限，用处不大）
    主界面和配置界面更漂亮、好用
*/

DoubleCommander:
    global DC_Class := "TTOTAL_CMD"
    global DC := "ahk_class " . DC_Class
    global DC_Dir := "c:\mine\app\doublecmd"
    global DC_Path := "c:\mine\app\doublecmd\doublecmd.exe --no-splash"
    ; 用于记录文件打开对话框所属窗体
    global DC_CallerId := 0

    DC_Name := "DoubleCommander"

    Vim.SetWin(DC_Name, DC_Class, "doublecmd.exe")
    Vim.Mode("normal", DC_Name)

    Vim.BeforeActionDo("DC_ForceInsertMode", DC_Name)
return

DC_ForceInsertMode() {
    ControlGetFocus, Ctrl
    if (InStr(Ctrl, "Edit") == 1) {
        return true
    }

    WinGet, MenuID, ID, AHK_CLASS #32768
    if (MenuID != "") {
        return true
    }

    return false
}

DC_Run(Cmd) {
    ControlSetText, Edit1, % Cmd, % DC
    ControlSend, Edit1, {Enter}, % DC
}

; 返回值 [1]: left/right [2]: 左侧面板所占比例 0-100
DC_GetPanelInfo() {
    ClipSaved := ClipboardAll
    Clipboard := ""
    DC_Run("cm_CopyPanelInfoToClip")
    ClipWait, 1

    PanelInfo := StrSplit(Clipboard, " ")
    Clipboard := ClipSaved

    return PanelInfo
}

DC_ExecuteToolbarItem(ID) {
    DC_Run("cm_ExecuteToolbarItem ToolItemID=" . ID)
}

DC_ColumnsView(ColumnSet) {
    if (ColumnSet == "") {
        DC_Run("cm_ColumnsView")
    } else {
        DC_Run("cm_ColumnsView columnset=" . ColumnSet)
    }
}

DC_OpenPath(Path, InNewTab := true, LeftOrRight := "") {
    LeftOfRight := DC_GetPanelInfo()[1]
    if (LeftOfRight == "right") {
        LeftOrRight := "-R"
    } else {
        LeftOrRight := "-L"
    }

    if (InNewTab) {
        Run, %DC_Path% -C -T "%LeftOrRight%" "%Path%"
    } else {
        Run, %DC_Path% -C "%LeftOrRight%" "%Path%"
    }
}

; funcend

<DC_Test>:
    ; DC_ExecuteToolbarItem("{700FF494-B939-48A3-B248-8823EB366AEA}")
    DC_Run("cm_About")
return

<DC_Restart>:
    WinClose, % DC
    WinWaitClose, % DC, , 2

    Run, % DC_Path

    WinWaitActive, % DC

    if (!WinExist(DC)) {
        MsgBox, 重启失败 %ErrorMessage%
    }
return

<DC_Show_50_50>:
    DC_Run("cm_PanelsSplitterPerPos splitpct=50")
return

<DC_Show_100_0>:
    DC_Run("cm_PanelsSplitterPerPos splitpct=100")
return

<DC_Show_0_100>:
    DC_Run("cm_PanelsSplitterPerPos splitpct=0")
return

<DC_HorizontalFilePanels>:
    DC_Run("cm_HorizontalFilePanels mode=legacy")
return

<DC_Toggle_50_100>:
    PanelInfo := DC_GetPanelInfo()

    if (Abs(50 - PanelInfo[2]) < 10) {
        if (PanelInfo[1] == "left") {
            DC_Run("cm_PanelsSplitterPerPos splitpct=100")
        } else {
            DC_Run("cm_PanelsSplitterPerPos splitpct=0")
        }
    } else {
        DC_Run("cm_PanelsSplitterPerPos splitpct=50")
    }
return

<DC_MakeDir>:
    DC_Run("cm_MakeDir")
return

<DC_PreviousParallelDir>:
    SleepTime := 10

    ClipSaved := ClipboardAll
    Clipboard := ""
    DC_Run("cm_CopyCurrentPathToClip")
    ClipWait, 1

    OldPwd := Clipboard

    if (InStr(OldPwd, "\") == 1) {
        ; 网络文件系统比较慢
        SleepTime := 50
    }

    if (StrLen(OldPwd) == 3) {
        ; 在根分区

        Clipboard := ClipSaved
        ClipSaved := ""

        return
    }

    DC_Run("cm_ChangeDirToParent")
    Sleep, % SleepTime

    DC_Run("cm_GoToPrevEntry")
    Sleep, % SleepTime

    Send, {Right}

    Clipboard := ClipSaved
    ClipSaved := ""
return

<DC_NextParallelDir>:
    SleepTime := 10

    ClipSaved := ClipboardAll
    Clipboard := ""
    DC_Run("cm_CopyCurrentPathToClip")
    ClipWait, 1

    OldPwd := Clipboard

    if (InStr(OldPwd, "\") == 1) {
        ; 网络文件系统比较慢
        SleepTime := 50
    }

    if (StrLen(OldPwd) == 3) {
        ; 在根分区
        ; Gosub, <cm_GotoPreviousDrive>

        Clipboard := ClipSaved
        ClipSaved := ""

        return
    }

    DC_Run("cm_ChangeDirToParent")
    Sleep, % SleepTime

    DC_Run("cm_GoToNextEntry")
    Sleep, % SleepTime

    Send, {Right}
    Sleep, % SleepTime

    Clipboard := ""
    DC_Run("cm_CopyCurrentPathToClip")
    ClipWait, 1

    if (OldPwd != Clipboard && InStr(OldPwd, Clipboard) == 1) {
        ; 下一个是文件
        DC_Run("cm_ViewHistoryPrev")
    }

    Clipboard := ClipSaved
    ClipSaved := ""
return

<DC_CreateNewFile>:
    ControlGetFocus, TLB, % DC
    ControlGetPos, Xn, Yn, , , % TLB, % DC

    Menu, NewFileMenu, Add
    Menu, NewFileMenu, DeleteAll
    Menu, NewFileMenu, Add , S >> 快捷方式, <DC_CreateFileShortcut>
    Menu, NewFileMenu, Icon, S >> 快捷方式, %A_WinDir%\system32\Shell32.dll, 264
    Menu, NewFileMenu, Add

    Loop, % DC_Dir . "\shellnew\*.*" {
        Ft := SubStr(A_LoopFileName, 1, 1) . " >> " . A_LoopFileName
        Menu, NewFileMenu, Add, % Ft, DC_NewFileMenuAction
        Menu, NewFileMenu, Icon, % Ft, %A_WinDir%\system32\Shell32.dll
    }

    Menu, NewFileMenu, Show, % Xn, % Yn + 2
return

DC_NewFileMenuAction:
    Filename := RegExReplace(A_ThisMenuItem, ".\s>>\s")
    FilePath := DC_Dir . "\ShellNew\" . Filename

    Gui, Destroy
    Gui, Add, Text, x12 y20 w50 h20 +Center, 模板源
    Gui, Add, Edit, x72 y20 w300 h20 Disabled, % FilePath
    Gui, Add, Text, x12 y50 w50 h20 +Center, 新建文件
    Gui, Add, Edit, x72 y50 w300 h20, % Filename
    Gui, Add, Button, x162 y80 w90 h30 gDC_NewFileOk default, 确认(&S)
    Gui, Add, Button, x282 y80 w90 h30 gDC_NewFileClose , 取消(&C)
    Gui, Show, w400 h120, 新建文件
return

DC_NewFileClose:
    Gui, Destroy
return

DC_NewFileOK:
    GuiControlGet, SrcFilePath, , Edit1
    GuiControlGet, NewFilename, , Edit2

    ClipSaved := ClipboardAll
    Clipboard :=
    DC_Run("cm_CopyCurrentPathToClip")
    ClipWait, 1
    DstPath := Clipboard
    Clipboard := ClipSaved
    ClipSaved := ""

    if (InStr(DstPath, "`r")) {
        DstPath := SubStr(DstPath, 1, InStr(DstPath, "`r") - 1)
    } else if (DstPath == "") {
        return
    }

    NewFilePath := DstPath . NewFilename
    if (FileExist(NewFilePath)) {
        MsgBox, 4, 新建文件, 新建文件已存在，是否覆盖？
        IfMsgBox No
            return
    }

    FileCopy, % SrcFilePath, % NewFilePath, 1

    ; 虽然不是完全匹配，基本也能用了
    DC_Run("cm_QuickSearch matchbeginning=on | text=" . NewFilename)

    Gui, Destroy
return

<DC_Toggle>:
    if (WinExist(DC)) {
        WinGet, Ac, MinMax, % DC
        if (Ac == -1) {
            WinActivate, % DC
        } else {
            if (!WinActive(DC)) {
                WinActivate, % DC
            } else {
                WinMinimize, % DC
            }
        }
    } else {
        Run, % DC_Path
        WinWait, % DC

        if (!WinActive(DC)) {
            WinActivate, % DC
        }
    }
return

<DC_SortByName>:
    DC_Run("cm_SortByName")
return

<DC_SortByExt>:
    DC_Run("cm_SortByExt")
return

<DC_SortBySize>:
    DC_Run("cm_SortBySize")
return

<DC_SortByDate>:
    DC_Run("cm_SortByDate")
return

<DC_SortByAttr>:
    DC_Run("cm_SortByAttr")
return

<DC_ReverseOrder>:
    DC_Run("cm_ReverseOrder")
return

<DC_FocusSwap>:
    DC_Run("cm_FocusSwap")
    ; side=left/right
return

<DC_CopyCurrentPathToClip>:
    DC_Run("cm_CopyCurrentPathToClip")
return

<DC_OpenExplorer>:
    DC_Run(".")
return

<DC_MarkFile>:
    DC_Run("cm_EditComment")
    ; 不要在已有备注的文件使用
    Send, ^+{End}🖥{F2}
return

<DC_UnMarkFile>:
    DC_Run("cm_EditComment")
    ; 删除 DC_MarkFile 的文件标记，也可用于清空文件备注
    Send, ^+{End}{Del}{F2}
return

<DC_ShowMainMenu>:
    DC_Run("cm_ShowMainMenu")
return

<DC_ShowButtonMenu>:
    DC_Run("cm_ShowButtonMenu")
return

<DC_OperationsViewer>:
    DC_Run("cm_OperationsViewer")
return

<DC_TreeView>:
    DC_Run("cm_TreeView")
return

<DC_FocusTreeView>:
    DC_Run("cm_FocusTreeView")
return

<DC_BriefView>:
    DC_Run("cm_BriefView")
return

<DC_ColumnsView1>:
    DC_ColumnsView("mine")
return

<DC_ColumnsView2>:
    DC_ColumnsView("test")
return

<DC_ThumbnailsView>:
    DC_Run("cm_ThumbnailsView")
    Gosub, <DC_ThumbnailsSwitchKey>
return

<DC_ThumbnailsSwitchKey>:
    InThumbsView := !InThumbsView

    if (InThumbsView) {
        Vim.Map("l", "<right>", DC_Name)
    } else {
        Vim.Map("l", "<enter>", DC_Name)
    }
return

<DC_ToggleShowInfo>:
    Vim.GetWin(DC_Name).SetInfo(!Vim.GetWin(DC_Name).info)
return

<DC_CopyFileContent>:
    Clipboard := ""
    DC_Run("cm_CopyFullNamesToClip")
    ClipWait, 1

    Fileread, Contents, % Clipboard
    Clipboard := Contents
return

<DC_CopyFilenamesOnly>:
    Clipboard := ""
    DC_Run("cm_CopyFullNamesToClip")
    ClipWait, 1

    SplitPath, Clipboard, OutFileName, , , OutFilenameNoExt

    if (InStr(FileExist(Clipboard), "D")) {
        Clipboard := OutFileName
    } else if (InStr(Clipboard, ".")) {
        Clipboard := OutFilenameNoExt
    }
return

<DC_CreateFileShortcut>:
    ClipSaved := ClipboardAll
    Clipboard := ""
    DC_Run("cm_CopyFullNamesToClip")
    ClipWait

    FilePath := Clipboard
    Clipboard := ClipSaved
    ClipSaved := ""

    OutVar := FileExist(FilePath)
    if (InStr(OutVar, "D")) {
        FileCreateShortcut, % FilePath, % FilePath . ".lnk"
    } else if (OutVar != "") {
        FileCreateShortcut, % FilePath, % RegExReplace(FilePath, "\.[^.]*$", ".lnk")
    }
return

<DC_Focus>:
    IfWinExist, % DC
        Winactivate, % DC
    else {
        Run, % DC_Path
        WinWait, % DC
        IfWinNotActive, % DC
            WinActivate, % DC
    }
return

<DC_MapKeys>:
	Vim.Mode("normal", DC_Name)
    Vim.Map("<S-Enter>", "<DC_SelectedCurrentDir>", DC_Name)
    Vim.Map("<Esc>", "<DC_ReturnToCaller>", DC_Name)
return

<DC_UnMapKeys>:
	Vim.Mode("normal", DC_Name)
    Vim.Map("<S-Enter>", "<Default>", DC_Name)
    Vim.Map("<Esc>", "<Default>", DC_Name)
return

; 返回调用者
<DC_ReturnToCaller>:
    gosub <DC_UnMapKeys>

    WinActivate, ahk_id %DC_CallerId%

    DC_CallerId := 0
return

; 非 TC 窗口按下后激活 TC 窗口
; TC 窗口按下后复制当前选中文件返回原窗口后粘贴
<DC_OpenDCDialog>:
    WinGetClass, name, A

    ; 在 DC 按下快捷键时，激活调用窗体并执行粘贴操作
    if (name == DC_Class) {
        if (DC_CallerId != 0) {
            gosub <DC_Selected>
            DC_CallerId := 0
		}
    } else {
        DC_CallerId := WinExist("A")
        if (DC_CallerId == 0) {
            return
		}

        gosub <DC_Focus>
        gosub <DC_MapKeys>
    }
return

<DC_Selected>:
    gosub <DC_UnMapKeys>

    Clipboard := ""
    ; 不知道什么原因，必须加一个 MsgBox 功能才正常
    MsgBox, , , 处理中, 0.3

    DC_Run("cm_CopyCurrentPathToClip")

    ClipWait, 1
    Pwd := Clipboard

    Clipboard := ""
    DC_Run("cm_CopyNamesToClip")
    ClipWait, 1

    WinActivate, ahk_id %DC_CallerId%
    WinWait, ahk_id %DC_CallerId%
    DC_CallerId := 0

    if (!InStr(Clipboard, "`n")) {
        Clipboard := Pwd . Clipboard
        Send, {Home}
        Send, ^v
        Send, {Enter}

        return
    }

    ; 多选

    Files := ""
    Loop, parse, Clipboard, `n, `r
        Files .= """" . A_LoopField  . """ "

    ; 第一步：跳转到当前路径
    Clipboard := Pwd
    Send, ^a
    Send, ^v
    Send, {Enter}
    sleep, 100

    ; 第二步：提交文件名
    Clipboard := Files
    Send, ^v
    Send, {Enter}
return

<DC_SelectedCurrentDir>:
    gosub <DC_UnMapKeys>

    if (DC_CallerId == 0) {
        return
    }

    Clipboard := ""
    DC_Run("cm_CopyCurrentPathToClip")
    ClipWait

    ; 添加默认路径不带反斜杠，添加之

    Clipboard .= "\"

    WinActivate, ahk_id %DC_CallerId%
    WinWait, ahk_id %DC_CallerId%
    DC_CallerId := 0

    Send, {Home}
    Send, ^v
    Send, {Enter}
return

<DC_FlatViewSel>:
    DC_Run("cm_FlatViewSel")
return