diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..c0a6a40 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "RichCode.ahk"] + path = RichCode.ahk + url = https://github.com/G33kDude/Richcode.ahk diff --git a/CodeQuickTester.ahk b/CodeQuickTester.ahk index 90a0531..4f533fc 100644 --- a/CodeQuickTester.ahk +++ b/CodeQuickTester.ahk @@ -17,17 +17,11 @@ FileEncoding, UTF-8 Settings := ( LTrim Join Comments { - "Font": { - "Typeface": "Microsoft Sans Serif", - "Size": 8, - "Bold": False - }, - ; Editor (colors are 0xBBGGRR) - "FGColor": 0xCDEDED, + "FGColor": 0xEDEDCD, "BGColor": 0x3F3F3F, "TabSize": 4, - "CodeFont": { + "Font": { "Typeface": "Consolas", "Size": 11, "Bold": False @@ -35,21 +29,22 @@ Settings := ; Highlighter (colors are 0xRRGGBB) "UseHighlighter": True, + "Highlighter": "HighlightAHK", "HighlightDelay": 200, ; Delay until the user is finished typing "Colors": [ - 0x7F9F7F, ; Comments - 0x7F9F7F, ; Multiline comments - 0x7CC8CF, ; Directives - 0x97C0EB, ; Punctuation - 0xF79B57, ; Numbers - 0xCC9893, ; Strings - 0xF79B57, ; A_Builtins - 0xE4EDED, ; Flow - 0xCDBFA3, ; Commands - 0x7CC8CF, ; Functions - 0xCB8DD9, ; Keynames - 0xE4EDED, ; Other keywords - 0xEDEDCD ; Text + ; RRGGBB ; ; AHK + 0x7F9F7F, ; 1 ; Comments + 0x7F9F7F, ; 2 ; Multiline comments + 0x7CC8CF, ; 3 ; Directives + 0x97C0EB, ; 4 ; Punctuation + 0xF79B57, ; 5 ; Numbers + 0xCC9893, ; 6 ; Strings + 0xF79B57, ; 7 ; A_Builtins + 0xE4EDED, ; 8 ; Flow + 0xCDBFA3, ; 9 ; Commands + 0x7CC8CF, ; 10 ; Functions + 0xCB8DD9, ; 11 ; Key names + 0xE4EDED ; 12 ; Other keywords ], ; Auto-Indenter @@ -90,11 +85,12 @@ TesterClose(Tester) return */ +#Include %A_ScriptDir%\RichCode.ahk\RichCode.ahk +#Include %A_ScriptDir%\RichCode.ahk\Highlighters\AHK.ahk #Include %A_ScriptDir%\lib #Include CQT.ahk #Include ServiceHandler.ahk #Include WinEvents.ahk #Include AutoIndent.ahk #Include Utils.ahk -#Include Publish.ahk -#Include Highlight.ahk \ No newline at end of file +#Include Publish.ahk \ No newline at end of file diff --git a/RichCode.ahk b/RichCode.ahk new file mode 160000 index 0000000..a61533c --- /dev/null +++ b/RichCode.ahk @@ -0,0 +1 @@ +Subproject commit a61533c357f02374fe128dd8b7fe299d7be98af0 diff --git a/lib/CQT.MenuButtons.ahk b/lib/CQT.MenuButtons.ahk index c828de2..93c7f56 100644 --- a/lib/CQT.MenuButtons.ahk +++ b/lib/CQT.MenuButtons.ahk @@ -12,7 +12,7 @@ class MenuButtons if ErrorLevel return - FileOpen(FilePath, "w").Write(this.Parent.Code) + FileOpen(FilePath, "w").Write(this.Parent.RichCode.Value) } Open() @@ -35,7 +35,7 @@ class MenuButtons if ErrorLevel return - FileOpen(FilePath, "w").Write(this.Parent.Code) + FileOpen(FilePath, "w").Write(this.Parent.RichCode.Value) PreprocessScript(Text, FilePath, []) FileOpen(FilePath, "w").Write(Text) } @@ -81,12 +81,14 @@ class MenuButtons Menu, % this.Parent.Menus[4], Check, &Highlighter else Menu, % this.Parent.Menus[4], Uncheck, &Highlighter - this.Parent.Code := this.Parent.Code + + ; Force refresh the code, adding/removing any highlighting + this.Parent.RichCode.Value := this.Parent.RichCode.Value } AutoIndent() { - this.Parent.LoadCode(AutoIndent(this.Parent.Code, this.Parent.Settings.Indent)) + this.Parent.LoadCode(AutoIndent(this.Parent.RichCode.Value, this.Parent.Settings.Indent)) } Help() @@ -121,107 +123,21 @@ class MenuButtons Comment() { - hCodeEditor := this.Parent.hCodeEditor - - Text := StrSplit(this.Parent.Code, "`n", "`r") - - VarSetCapacity(s, 8, 0), SendMessage(0x0B0, &s, &s+4, hCodeEditor) ; EM_GETSEL - Left := NumGet(s, 0, "UInt"), Right := NumGet(s, 4, "UInt") - - Top := SendMessage(0x436, 0, Left, hCodeEditor) ; EM_EXLINEFROMCHAR - Bottom := SendMessage(0x436, 0, Right, hCodeEditor) ; EM_EXLINEFROMCHAR - - Count := Bottom-Top + 1 - Loop, % Count - Text[A_Index+Top] := ";" Text[A_Index+Top] - for each, Line in Text - Out .= "`r`n" Line - Out := SubStr(Out, 3) - - this.Parent.Code := Out - - NumPut(NumGet(s, "UInt") + 1, &s, "UInt") - NumPut(NumGet(s, 4, "UInt") + Count, &s, 4, "UInt") - SendMessage(0x437, 0, &s, hCodeEditor) ; EM_EXSETSEL + this.Parent.RichCode.IndentSelection(False, ";") } Uncomment() { - hCodeEditor := this.Parent.hCodeEditor - - Text := StrSplit(this.Parent.Code, "`n", "`r") - - VarSetCapacity(s, 8, 0), SendMessage(0x0B0, &s, &s+4, hCodeEditor) ; EM_GETSEL - Left := NumGet(s, 0, "UInt"), Right := NumGet(s, 4, "UInt") - - Top := SendMessage(0x436, 0, Left, hCodeEditor) ; EM_EXLINEFROMCHAR - Bottom := SendMessage(0x436, 0, Right, hCodeEditor) ; EM_EXLINEFROMCHAR - - Removed := 0 - Loop, % Bottom-Top + 1 - if InStr(Text[A_Index+Top], ";") == 1 - Text[A_Index+Top] := SubStr(Text[A_Index+Top], 2), Removed++ - for each, Line in Text - Out .= "`r`n" Line - Out := SubStr(Out, 3) - - this.Parent.Code := Out - - NumPut(NumGet(s, "UInt") - 1, &s, "UInt") - NumPut(NumGet(s, 4, "UInt") - Removed, &s, 4, "UInt") - SendMessage(0x437, 0, &s, hCodeEditor) ; EM_EXSETSEL + this.Parent.RichCode.IndentSelection(True, ";") } Indent() { - hCodeEditor := this.Parent.hCodeEditor - - Text := StrSplit(this.Parent.Code, "`n", "`r") - - VarSetCapacity(s, 8, 0), SendMessage(0x0B0, &s, &s+4, hCodeEditor) ; EM_GETSEL - Left := NumGet(s, 0, "UInt"), Right := NumGet(s, 4, "UInt") - - Top := SendMessage(0x436, 0, Left, hCodeEditor) ; EM_EXLINEFROMCHAR - Bottom := SendMessage(0x436, 0, Right, hCodeEditor) ; EM_EXLINEFROMCHAR - - Count := Bottom-Top + 1 - Loop, % Count - Text[A_Index+Top] := "`t" Text[A_Index+Top] - for each, Line in Text - Out .= "`r`n" Line - Out := SubStr(Out, 3) - - this.Parent.Code := Out - - NumPut(NumGet(s, "UInt") + 1, &s, "UInt") - NumPut(NumGet(s, 4, "UInt") + Count, &s, 4, "UInt") - SendMessage(0x437, 0, &s, hCodeEditor) ; EM_EXSETSEL + this.Parent.RichCode.IndentSelection() } Unindent() { - hCodeEditor := this.Parent.hCodeEditor - - Text := StrSplit(this.Parent.Code, "`n", "`r") - - VarSetCapacity(s, 8, 0), SendMessage(0x0B0, &s, &s+4, hCodeEditor) ; EM_GETSEL - Left := NumGet(s, 0, "UInt"), Right := NumGet(s, 4, "UInt") - - Top := SendMessage(0x436, 0, Left, hCodeEditor) ; EM_EXLINEFROMCHAR - Bottom := SendMessage(0x436, 0, Right, hCodeEditor) ; EM_EXLINEFROMCHAR - - Removed := 0 - Loop, % Bottom-Top + 1 - if InStr(Text[A_Index+Top], "`t") == 1 - Text[A_Index+Top] := SubStr(Text[A_Index+Top], 2), Removed++ - for each, Line in Text - Out .= "`r`n" Line - Out := SubStr(Out, 3) - - this.Parent.Code := Out - - NumPut(NumGet(s, "UInt") - 1, &s, "UInt") - NumPut(NumGet(s, 4, "UInt") - Removed, &s, 4, "UInt") - SendMessage(0x437, 0, &s, hCodeEditor) ; EM_EXSETSEL + this.Parent.RichCode.IndentSelection(True) } } diff --git a/lib/CQT.Paste.ahk b/lib/CQT.Paste.ahk index e4eed3f..c7a951d 100644 --- a/lib/CQT.Paste.ahk +++ b/lib/CQT.Paste.ahk @@ -8,7 +8,6 @@ class Paste Gui, New, +Owner%ParentWnd% +ToolWindow +hWndhWnd this.hWnd := hWnd Gui, Margin, 5, 5 - Gui, Font, % this.Parent.Settings.Font, % this.Parent.Settings.TypeFace Gui, Add, Text, xm ym w30 h22 +0x200, Desc: ; 0x200 for vcenter Gui, Add, Edit, x+5 yp w125 h22 hWndhPasteDesc, % this.Parent.Settings.DefaultDesc @@ -51,7 +50,7 @@ class Paste GuiControlGet, PasteChan,, % this.hPasteChan this.GuiClose() - Link := Ahkbin(this.Parent.Code, PasteName, PasteDesc, PasteChan) + Link := Ahkbin(this.Parent.RichCode.Value, PasteName, PasteDesc, PasteChan) MsgBox, 292, % this.Parent.Title " - Pasted", Link received:`n%Link%`n`nCopy to clipboard? IfMsgBox, Yes diff --git a/lib/CQT.ahk b/lib/CQT.ahk index d254473..6908cc3 100644 --- a/lib/CQT.ahk +++ b/lib/CQT.ahk @@ -61,22 +61,21 @@ class CodeQuickTester Menu, % this.Menus[4], Check, &Highlighter ; Add code editor - Gui, Font - , % "s" this.Settings.CodeFont.Size - . " w" (this.Settings.CodeFont.Bold ? "Bold" : "Norm") - , % this.Settings.CodeFont.Typeface - this.InitRichEdit() - Gui, Font - , % "s" this.Settings.Font.Size - . " w" (this.Settings.Font.Bold ? "Bold" : "Norm") - , % this.Settings.Font.Typeface + this.RichCode := new RichCode(this.Settings) - ; Get starting tester contents - FilePath := B_Params[1] ? RegExReplace(B_Params[1], "^ahk:") : this.DefaultPath - try - this.Code := FileExist(FilePath) ? FileOpen(FilePath, "r").Read() : UrlDownloadToVar(FilePath) + if B_Params.HasKey(1) + FilePath := RegExReplace(B_Params[1], "^ahk:") ; Remove leading service handler + else + FilePath := this.DefaultPath + + if (FilePath ~= "^https?://") + this.RichCode.Value := UrlDownloadToVar(FilePath) + else + this.RichCode.Value := FileOpen(FilePath, "r").Read() + + ; Place cursor after the default template text if (FilePath == this.DefaultPath) - SendMessage, 0x0B1, -1, -1,, % "ahk_id" this.hCodeEditor ; EM_SETSEL bottom of document + this.RichCode.Selection := [-1, -1] ; Add run button Gui, Add, Button, hWndhRunButton, &Run @@ -97,53 +96,6 @@ class CodeQuickTester Gui, Show, w640 h480, % this.Title } - InitRichEdit() - { - Settings := this.Settings - Gui, Add, Custom, ClassRichEdit50W hWndhCodeEditor +0x5031b1c4 +E0x20000 - this.hCodeEditor := hCodeEditor - - ; Register for WM_COMMAND and WM_NOTIFY events - ; NOTE: this prevents garbage collection of - ; the class until the control is destroyed - SendMessage, 0x445, 0, 1,, ahk_id %hCodeEditor% ; EM_SETEVENTMASK ENM_CHANGE - CtrlEvent := this.CtrlEvent.Bind(this) - GuiControl, +g, %hCodeEditor%, %CtrlEvent% - - ; Set background color - SendMessage, 0x443, 0, Settings.BGColor,, ahk_id %hCodeEditor% ; EM_SETBKGNDCOLOR - - ; Set FG color - VarSetCapacity(CharFormat, 116, 0) - NumPut(116, CharFormat, 0, "UInt") ; cbSize := sizeOf(CHARFORMAT2) - NumPut(0x40000000, CharFormat, 4, "UInt") ; dwMask := CFM_COLOR - NumPut(Settings.FGColor, CharFormat, 20, "UInt") ; crTextColor := 0xBBGGRR - SendMessage, 0x444, 0, &CharFormat,, ahk_id %hCodeEditor% ; EM_SETCHARFORMAT - - ; Set tab size to 4 for non-highlighted code - VarSetCapacity(TabStops, 4, 0), NumPut(Settings.TabSize*4, TabStops, "UInt") - SendMessage, 0x0CB, 1, &TabStops,, ahk_id %hCodeEditor% ; EM_SETTABSTOPS - - ; Change text limit from 32,767 to max - SendMessage, 0x435, 0, -1,, ahk_id %hCodeEditor% ; EM_EXLIMITTEXT - } - - Code[] - { - get { - GuiControlGet, CodeEditor,, % this.hCodeEditor - return CodeEditor - } - - set { - if this.Settings.UseHighlighter - this.Highlight(Value) - else - GuiControl,, % this.hCodeEditor, %Value% - return Value - } - } - RunButton() { if (this.Exec.Status == 0) ; Running @@ -152,7 +104,7 @@ class CodeQuickTester { ; GuiControlGet, Params, Params: - Code := this.Code ; A temp var to avoid duplication of GuiControlGet + Code := this.RichCode.Value ; A temp var to avoid duplication of GuiControlGet this.Exec := ExecScript(Code, "", DeHashBang(Code)) ; TODO: Implement Params GuiControl,, % this.hRunButton, &Kill @@ -171,7 +123,7 @@ class CodeQuickTester LoadCode(Code) { - CodeEditor := this.Code + CodeEditor := this.RichCode.Value if (CodeEditor && CodeEditor != Code) ; TODO: Do I need to Trim() here? { Gui, +OwnDialogs @@ -179,58 +131,25 @@ class CodeQuickTester IfMsgBox, No return } - this.Code := Code + this.RichCode.Value := Code this.UpdateStatusBar() } OnMessage(wParam, lParam, Msg, hWnd) { - if (hWnd == this.hCodeEditor) + if (hWnd == this.RichCode.hWnd) { - if (Msg == 0x100) ; WM_KEYDOWN - { - if (wParam == GetKeyVK("Tab")) - { - ControlGet, Selected, Selected,,, % "ahk_id" this.hCodeEditor - if (Selected == "" && !GetKeyState("Shift")) - SendMessage, 0xC2, 1, &(x:="`t"),, % "ahk_id" this.hCodeEditor ; EM_REPLACESEL - else if GetKeyState("Shift") - this.Bound.Unindent() - else - this.Bound.Indent() - this.UpdateStatusBar() - return False - } - else if (wParam == GetKeyVK("Escape")) - return False - else if (wParam == GetKeyVK("v") && GetKeyState("Ctrl")) - { - SendMessage, 0xC2, 1, &(x:=Clipboard),, % "ahk_id" this.hCodeEditor ; EM_REPLACESEL - this.UpdateStatusBar() - return False - } - } - ; Call UpdateStatusBar after the edit handles the keystroke SetTimer(this.Bound.UpdateStatusBar, -0) } } - CtrlEvent(CtrlHwnd, GuiEvent, EventInfo, _ErrorLevel:="") - { - if (GuiEvent == "Normal" && EventInfo == 0x300) ; EN_CHANGE - { - ; Delay until the user is finished changing the document - SetTimer(this.Bound.Highlight, -Abs(this.Settings.HighlightDelay)) - } - } - UpdateStatusBar() { ; Delete the timer if it was called by one SetTimer(this.Bound.UpdateStatusBar, "Delete") - hCodeEditor := this.hCodeEditor + hCodeEditor := this.RichCode.hWnd hMainWindow := this.hMainWindow Gui, %hMainWindow%:Default @@ -244,88 +163,13 @@ class CodeQuickTester SB_SetText("Line " Row, 2) SB_SetText("Col " Col, 3) - VarSetCapacity(s, 8, 0) - SendMessage, 0x0B0, &s+0, &s+4,, ahk_id %hCodeEditor% ; EM_GETSEL - Left := NumGet(s, 0, "UInt"), Right := NumGet(s, 4, "UInt") - Len := Right - Left - (Right > Len) ; > is a workaround for being able to select the end of the document with RE + Selection := this.RichCode.Selection + ; If the user has selected 1 char further than the end of the document, + ; which is allowed in a RichEdit control, subtract 1 from the length + Len := Selection[2] - Selection[1] - (Selection[2] > Len) SB_SetText(Len > 0 ? "Selection Length: " Len : "", 4) ; >0 because sometimes it comes up as -1 if you hold down paste } - Highlight(NewCode:="") - { - if !this.Settings.UseHighlighter - return - - hCodeEditor := this.hCodeEditor - - ; Buffer any input events while the highlighter is running - Crit := A_IsCritical - Critical, 1000 - - ; Run the highlighter - Text := Highlight(NewCode == "" ? this.Code : NewCode, this.Settings) - - ; "TRichEdit suspend/resume undo function" - ; https://stackoverflow.com/a/21206620 - - ; Get the ITextDocument object - EM_GETOLEINTERFACE:=(0x400 + 60) - VarSetCapacity(pIRichEditOle, A_PtrSize, 0) - SendMessage, EM_GETOLEINTERFACE, 0, &pIRichEditOle,, ahk_id %hCodeEditor% - pIRichEditOle := NumGet(pIRichEditOle, 0, "UPtr") - IID_ITextDocument := "{8CC497C0-A1DF-11CE-8098-00AA0047BE5D}" - IRichEditOle := ComObject(9, pIRichEditOle, 1), ObjAddRef(pIRichEditOle) - pITextDocument := ComObjQuery(IRichEditOle, IID_ITextDocument) - ITextDocument := ComObject(9, pITextDocument, 1), ObjAddRef(pITextDocument) - - ; Ignore changes, freeze the renderer, and suspend the undo buffer - SendMessage, 0x445, 0, 0,, ahk_id %hCodeEditor% ; EM_SETEVENTMASK ENM_NONE - try - { - ; Not implemented in WINE - ITextDocument.Freeze() - ITextDocument.Undo(-9999995) ; tomSuspend - } - catch - GuiControl, -Redraw, %hCodeEditor% - - ; Save the text to a UTF-8 buffer - VarSetCapacity(Buf, StrPut(Text, "UTF-8"), 0) - StrPut(Text, &Buf, "UTF-8") - - ; Set up the necessary structs - VarSetCapacity(POINT , 8, 0) ; Scroll position - VarSetCapacity(CHARRANGE, 8, 0) ; Selection - VarSetCapacity(SETTEXTEX, 8, 0) ; SetText Settings - NumPut(1, SETTEXTEX, 0, "UInt") ; flags = ST_KEEPUNDO - - ; Save the scroll and cursor positions, update the text, - ; then restore the scroll and cursor positions - SendMessage, 0x4DD, 0, &POINT,, ahk_id %hCodeEditor% ; EM_GETSCROLLPOS - SendMessage, 0x434, 0, &CHARRANGE,, ahk_id %hCodeEditor% ; EM_EXGETSEL - SendMessage, 0x461, &SETTEXTEX, &Buf,, ahk_id %hCodeEditor% ; EM_SETTEXTEX - SendMessage, 0x437, 0, &CHARRANGE,, ahk_id %hCodeEditor% ; EM_EXSETSEL - SendMessage, 0x4DE, 0, &POINt,, ahk_id %hCodeEditor% ; EM_SETSCROLLPOS - - ; Resume the undo buffer, unfreeze the renderer, and listen for changes - try - { - ; Not implemented in WINE - ITextDocument.Undo(-9999994) ; tomResume - ITextDocument.Unfreeze() - } - catch - GuiControl, +Redraw, %hCodeEditor% - SendMessage, 0x445, 0, 1,, ahk_id %hCodeEditor% ; EM_SETEVENTMASK ENM_CHANGE - - ; Release the ITextDocument object - ITextDocument := "", IRichEditOle := "" - ObjRelease(pIRichEditOle), ObjRelease(pITextDocument) - - ; Resume event processing - Critical, %Crit% - } - RegisterCloseCallback(CloseCallback) { this.CloseCallback := CloseCallback @@ -333,7 +177,7 @@ class CodeQuickTester GuiSize() { - GuiControl, Move, % this.hCodeEditor, % "x" 5 "y" 5 "w" A_GuiWidth-10 "h" A_GuiHeight-60 + GuiControl, Move, % this.RichCode.hWnd, % "x" 5 "y" 5 "w" A_GuiWidth-10 "h" A_GuiHeight-60 GuiControl, Move, % this.hRunButton, % "x" 5 "y" A_GuiHeight-50 "w" A_GuiWidth-10 "h" 22 } @@ -345,7 +189,7 @@ class CodeQuickTester GuiClose() { - if Trim(this.Code, " `t`r`n") ; TODO: Check against last saved code + if Trim(this.RichCode.Value, " `t`r`n") ; TODO: Check against last saved code { Gui, +OwnDialogs MsgBox, 308, % this.Title " - Confirm Exit", Are you sure you want to exit? diff --git a/lib/Highlight.ahk b/lib/Highlight.ahk deleted file mode 100644 index b344175..0000000 --- a/lib/Highlight.ahk +++ /dev/null @@ -1,128 +0,0 @@ -Highlight(ByRef Code, Settings) -{ - static Flow := "break|byref|catch|class|continue|else|exit|exitapp|finally|for|global|gosub|goto|if|ifequal|ifexist|ifgreater|ifgreaterorequal|ifinstring|ifless|iflessorequal|ifmsgbox|ifnotequal|ifnotexist|ifnotinstring|ifwinactive|ifwinexist|ifwinnotactive|ifwinnotexist|local|loop|onexit|pause|return|settimer|sleep|static|suspend|throw|try|until|var|while" - , Commands := "autotrim|blockinput|clipwait|control|controlclick|controlfocus|controlget|controlgetfocus|controlgetpos|controlgettext|controlmove|controlsend|controlsendraw|controlsettext|coordmode|critical|detecthiddentext|detecthiddenwindows|drive|driveget|drivespacefree|edit|envadd|envdiv|envget|envmult|envset|envsub|envupdate|fileappend|filecopy|filecopydir|filecreatedir|filecreateshortcut|filedelete|fileencoding|filegetattrib|filegetshortcut|filegetsize|filegettime|filegetversion|fileinstall|filemove|filemovedir|fileread|filereadline|filerecycle|filerecycleempty|fileremovedir|fileselectfile|fileselectfolder|filesetattrib|filesettime|formattime|getkeystate|groupactivate|groupadd|groupclose|groupdeactivate|gui|guicontrol|guicontrolget|hotkey|imagesearch|inidelete|iniread|iniwrite|input|inputbox|keyhistory|keywait|listhotkeys|listlines|listvars|menu|mouseclick|mouseclickdrag|mousegetpos|mousemove|msgbox|outputdebug|pixelgetcolor|pixelsearch|postmessage|process|progress|random|regdelete|regread|regwrite|reload|run|runas|runwait|send|sendevent|sendinput|sendlevel|sendmessage|sendmode|sendplay|sendraw|setbatchlines|setcapslockstate|setcontroldelay|setdefaultmousespeed|setenv|setformat|setkeydelay|setmousedelay|setnumlockstate|setregview|setscrolllockstate|setstorecapslockmode|settitlematchmode|setwindelay|setworkingdir|shutdown|sort|soundbeep|soundget|soundgetwavevolume|soundplay|soundset|soundsetwavevolume|splashimage|splashtextoff|splashtexton|splitpath|statusbargettext|statusbarwait|stringcasesense|stringgetpos|stringleft|stringlen|stringlower|stringmid|stringreplace|stringright|stringsplit|stringtrimleft|stringtrimright|stringupper|sysget|thread|tooltip|transform|traytip|urldownloadtofile|winactivate|winactivatebottom|winclose|winget|wingetactivestats|wingetactivetitle|wingetclass|wingetpos|wingettext|wingettitle|winhide|winkill|winmaximize|winmenuselectitem|winminimize|winminimizeall|winminimizeallundo|winmove|winrestore|winset|winsettitle|winshow|winwait|winwaitactive|winwaitclose|winwaitnotactive" - , Functions := "abs|acos|array|asc|asin|atan|ceil|chr|comobjactive|comobjarray|comobjconnect|comobjcreate|comobject|comobjenwrap|comobjerror|comobjflags|comobjget|comobjmissing|comobjparameter|comobjquery|comobjtype|comobjunwrap|comobjvalue|cos|dllcall|exception|exp|fileexist|fileopen|floor|func|getkeyname|getkeysc|getkeystate|getkeyvk|il_add|il_create|il_destroy|instr|isbyref|isfunc|islabel|isobject|isoptional|ln|log|ltrim|lv_add|lv_delete|lv_deletecol|lv_getcount|lv_getnext|lv_gettext|lv_insert|lv_insertcol|lv_modify|lv_modifycol|lv_setimagelist|mod|numget|numput|objaddref|objclone|object|objgetaddress|objgetcapacity|objhaskey|objinsert|objinsertat|objlength|objmaxindex|objminindex|objnewenum|objpop|objpush|objrawset|objrelease|objremove|objremoveat|objsetcapacity|onmessage|ord|regexmatch|regexreplace|registercallback|round|rtrim|sb_seticon|sb_setparts|sb_settext|sin|sqrt|strget|strlen|strput|strsplit|substr|tan|trim|tv_add|tv_delete|tv_get|tv_getchild|tv_getcount|tv_getnext|tv_getparent|tv_getprev|tv_getselection|tv_gettext|tv_modify|tv_setimagelist|varsetcapacity|winactive|winexist|_addref|_clone|_getaddress|_getcapacity|_haskey|_insert|_maxindex|_minindex|_newenum|_release|_remove|_setcapacity" - , Keynames := "alt|altdown|altup|appskey|backspace|blind|browser_back|browser_favorites|browser_forward|browser_home|browser_refresh|browser_search|browser_stop|bs|capslock|click|control|ctrl|ctrlbreak|ctrldown|ctrlup|del|delete|down|end|enter|esc|escape|f1|f10|f11|f12|f13|f14|f15|f16|f17|f18|f19|f2|f20|f21|f22|f23|f24|f3|f4|f5|f6|f7|f8|f9|home|ins|insert|joy1|joy10|joy11|joy12|joy13|joy14|joy15|joy16|joy17|joy18|joy19|joy2|joy20|joy21|joy22|joy23|joy24|joy25|joy26|joy27|joy28|joy29|joy3|joy30|joy31|joy32|joy4|joy5|joy6|joy7|joy8|joy9|joyaxes|joybuttons|joyinfo|joyname|joypov|joyr|joyu|joyv|joyx|joyy|joyz|lalt|launch_app1|launch_app2|launch_mail|launch_media|lbutton|lcontrol|lctrl|left|lshift|lwin|lwindown|lwinup|mbutton|media_next|media_play_pause|media_prev|media_stop|numlock|numpad0|numpad1|numpad2|numpad3|numpad4|numpad5|numpad6|numpad7|numpad8|numpad9|numpadadd|numpadclear|numpaddel|numpaddiv|numpaddot|numpaddown|numpadend|numpadenter|numpadhome|numpadins|numpadleft|numpadmult|numpadpgdn|numpadpgup|numpadright|numpadsub|numpadup|pause|pgdn|pgup|printscreen|ralt|raw|rbutton|rcontrol|rctrl|right|rshift|rwin|rwindown|rwinup|scrolllock|shift|shiftdown|shiftup|space|tab|up|volume_down|volume_mute|volume_up|wheeldown|wheelleft|wheelright|wheelup|xbutton1|xbutton2" - , Builtins := "base|clipboard|clipboardall|comspec|errorlevel|false|programfiles|true" - , Keywords := "abort|abovenormal|activex|add|ahk_class|ahk_exe|ahk_group|ahk_id|ahk_pid|all|alnum|alpha|altsubmit|alttab|alttabandmenu|alttabmenu|alttabmenudismiss|alwaysontop|and|autosize|background|backgroundtrans|base|belownormal|between|bitand|bitnot|bitor|bitshiftleft|bitshiftright|bitxor|bold|border|bottom|button|buttons|cancel|capacity|caption|center|check|check3|checkbox|checked|checkedgray|choose|choosestring|click|clone|close|color|combobox|contains|controllist|controllisthwnd|count|custom|date|datetime|days|ddl|default|delete|deleteall|delimiter|deref|destroy|digit|disable|disabled|dpiscale|dropdownlist|edit|eject|enable|enabled|error|exit|expand|exstyle|extends|filesystem|first|flash|float|floatfast|focus|font|force|fromcodepage|getaddress|getcapacity|grid|group|groupbox|guiclose|guicontextmenu|guidropfiles|guiescape|guisize|haskey|hdr|hidden|hide|high|hkcc|hkcr|hkcu|hkey_classes_root|hkey_current_config|hkey_current_user|hkey_local_machine|hkey_users|hklm|hku|hotkey|hours|hscroll|hwnd|icon|iconsmall|id|idlast|ignore|imagelist|in|insert|integer|integerfast|interrupt|is|italic|join|label|lastfound|lastfoundexist|left|limit|lines|link|list|listbox|listview|localsameasglobal|lock|logoff|low|lower|lowercase|ltrim|mainwindow|margin|maximize|maximizebox|maxindex|menu|minimize|minimizebox|minmax|minutes|monitorcount|monitorname|monitorprimary|monitorworkarea|monthcal|mouse|mousemove|mousemoveoff|move|multi|na|new|no|noactivate|nodefault|nohide|noicon|nomainwindow|norm|normal|nosort|nosorthdr|nostandard|not|notab|notimers|number|off|ok|on|or|owndialogs|owner|parse|password|pic|picture|pid|pixel|pos|pow|priority|processname|processpath|progress|radio|range|rawread|rawwrite|read|readchar|readdouble|readfloat|readint|readint64|readline|readnum|readonly|readshort|readuchar|readuint|readushort|realtime|redraw|regex|region|reg_binary|reg_dword|reg_dword_big_endian|reg_expand_sz|reg_full_resource_descriptor|reg_link|reg_multi_sz|reg_qword|reg_resource_list|reg_resource_requirements_list|reg_sz|relative|reload|remove|rename|report|resize|restore|retry|rgb|right|rtrim|screen|seconds|section|seek|send|sendandmouse|serial|setcapacity|setlabel|shiftalttab|show|shutdown|single|slider|sortdesc|standard|status|statusbar|statuscd|strike|style|submit|sysmenu|tab|tab2|tabstop|tell|text|theme|this|tile|time|tip|tocodepage|togglecheck|toggleenable|toolwindow|top|topmost|transcolor|transparent|tray|treeview|type|uncheck|underline|unicode|unlock|updown|upper|uppercase|useenv|useerrorlevel|useunsetglobal|useunsetlocal|vis|visfirst|visible|vscroll|waitclose|wantctrla|wantf2|wantreturn|wanttab|wrap|write|writechar|writedouble|writefloat|writeint|writeint64|writeline|writenum|writeshort|writeuchar|writeuint|writeushort|xdigit|xm|xp|xs|yes|ym|yp|ys|__call|__delete|__get|__handle|__new|__set" - , Needle := " - ( LTrim Join Comments - ODims) - ((?:^|\s);[^\n]+) ; Comments - |(^\s*\/\*.+?\n\s*\*\/) ; Multiline comments - |((?:^|\s)#[^ \t\r\n,]+) ; Directives - |([+*!~&\/\\<>^|=?: - ,().```%{}\[\]\-]+) ; Punctuation - |(0x[0-9a-fA-F]+|[0-9]+) ; Numbers - |(""[^""\r\n]*"") ; Strings - |\b(A_\w*|" Builtins ")\b ; A_Builtins - |\b(" Flow ")\b ; Flow - |\b(" Commands ")\b ; Commands - |\b(" Functions ")\b ; Functions - |\b(" Keynames ")\b ; Keynames - |\b(" Keywords ")\b ; Other keywords - )" - - FontTable := "{\fonttbl{\f0\fnil\fcharset0 " - FontTable .= Settings.CodeFont.Typeface - FontTable .= ";}}" - - ColorTable := "{\colortbl" - for each, Color in Settings.Colors - { - ColorTable .= ";\red" Color>>16 & 0xFF - ColorTable .= "\green" Color>>8 & 0xFF - ColorTable .= "\blue" Color & 0xFF - } - ColorTable .= ";}" - - RTF := "{\urtf" - RTF .= FontTable - RTF .= ColorTable - RTF .= "\fs" Settings.CodeFont.Size * 2 ; Font size (half-points) - RTF .= "\deftab" GetCharWidthTwips(Settings.CodeFont) * Settings.TabSize ; Tab size (twips) - if Settings.CodeFont.Bold - RTF .= "\b" - - Pos := 1 - while (FoundPos := RegExMatch(Code, Needle, Match, Pos)) - { - RTF .= "\cf13 " EscapeRTF(SubStr(Code, Pos, FoundPos-Pos)) "\cf" - - if (Match.Value(1) != "") - RTF .= 1 - else if (Match.Value(2) != "") - RTF .= 2 - else if (Match.Value(3) != "") - RTF .= 3 - else if (Match.Value(4) != "") - RTF .= 4 - else if (Match.Value(5) != "") - RTF .= 5 - else if (Match.Value(6) != "") - RTF .= 6 - else if (Match.Value(7) != "") - RTF .= 7 - else if (Match.Value(8) != "") - RTF .= 8 - else if (Match.Value(9) != "") - RTF .= 9 - else if (Match.Value(10) != "") - RTF .= 10 - else if (Match.Value(11) != "") - RTF .= 11 - else if (Match.Value(12) != "") - RTF .= 12 - else - RTF .= 13 - - RTF .= " " EscapeRTF(Match.Value()) - Pos := FoundPos + Match.Len() - } - - return RTF "\cf13 " EscapeRTF(SubStr(Code, Pos)) "\`n}" -} - -GetCharWidthTwips(Font) -{ - static Cache := {} - - if Cache.HasKey(Font.Typeface "_" Font.Size "_" Font.Bold) - return Cache[Font.Typeface "_" font.Size "_" Font.Bold] - - hDC := DllCall("GetDC", "UPtr", 0) - hFont := DllCall("CreateFont" - , "Int", -Round(Font.Size*A_ScreenDPI/72) ; _In_ int nHeight, - , "Int", 0 ; _In_ int nWidth, - , "Int", 0 ; _In_ int nEscapement, - , "Int", 0 ; _In_ int nOrientation, - , "Int", 400+300*(!!Font.Bold) ; _In_ int fnWeight, - , "UInt", 0 ; _In_ DWORD fdwItalic, - , "UInt", 0 ; _In_ DWORD fdwUnderline, - , "UInt", 0 ; _In_ DWORD fdwStrikeOut, - , "UInt", 0 ; _In_ DWORD fdwCharSet, (ANSI_CHARSET) - , "UInt", 0 ; _In_ DWORD fdwOutputPrecision, (OUT_DEFAULT_PRECIS) - , "UInt", 0 ; _In_ DWORD fdwClipPrecision, (CLIP_DEFAULT_PRECIS) - , "UInt", 0 ; _In_ DWORD fdwQuality, (DEFAULT_QUALITY) - , "UInt", 0 ; _In_ DWORD fdwPitchAndFamily, (FF_DONTCARE|DEFAULT_PITCH) - , "Str", Font.Typeface ; _In_ LPCTSTR lpszFace - , "UPtr") - hObj := DllCall("SelectObject", "UPtr", hDC, "UPtr", hFont, "UPtr") - VarSetCapacity(SIZE, 8, 0) - DllCall("GetTextExtentPoint32", "UPtr", hDC, "Str", "x", "Int", 1, "UPtr", &SIZE) - DllCall("SelectObject", "UPtr", hDC, "UPtr", hObj, "UPtr") - DllCall("DeleteObject", "UPtr", hFont) - DllCall("ReleaseDC", "UPtr", 0, "UPtr", hDC) - - Twips := Round(NumGet(SIZE, 0, "UInt")*1440/A_ScreenDPI) - Cache[Font.Typeface "_" Font.Size "_" Font.Bold] := Twips - return Twips -} - -EscapeRTF(Code) -{ - for each, Char in ["\", "{", "}", "`n"] - Code := StrReplace(Code, Char, "\" Char) - return StrReplace(StrReplace(Code, "`t", "\tab "), "`r") -}