wxID_FINDNEXT = wx.wxID_HIGHEST + 20 wxID_FINDPREV = wx.wxID_HIGHEST + 30 wxID_REPLACE = wx.wxID_HIGHEST + 40 wxID_GOTOLINE = wx.wxID_HIGHEST + 50 editor = nil function createEditor(parent) editor = wxstc.wxStyledTextCtrl(parent, wx.wxID_ANY, wx.wxDefaultPosition, gui.EditFile:GetClientSize(), wx.wxSUNKEN_BORDER) local font local fontItalic if wx.wxPlatformWindows then font = wx.wxFont(10, wx.wxNORMAL, wx.wxNORMAL, wx.wxNORMAL, false, "Andale Mono") fontItalic = wx.wxFont(10, wx.wxNORMAL, wx.wxFONTSTYLE_ITALIC, wx.wxNORMAL, false, "Andale Mono") else font = wx.wxFont(12, wx.wxNORMAL, wx.wxNORMAL, wx.wxNORMAL, false, "lucidatypewriter") fontItalic = wx.wxFont(12, wx.wxNORMAL, wx.wxFONTSTYLE_ITALIC, wx.wxNORMAL, false, "lucidatypewriter") end editor:SetAutoLayout(true) editor:SetBufferedDraw(true) editor:SetFont(font) editor:StyleSetFont(wxstc.wxSTC_STYLE_DEFAULT, font) editor:StyleClearAll() editor:StyleSetForeground(0, wx.wxColour(128, 128, 128)) -- White space editor:StyleSetForeground(1, wx.wxColour(0, 127, 0)) -- Comment editor:StyleSetFont(1, fontItalic) editor:StyleSetUnderline(1, false) editor:StyleSetForeground(2, wx.wxColour(0, 127, 0)) -- Line Comment editor:StyleSetFont(2, fontItalic) -- Doc. Comment editor:StyleSetUnderline(2, false) editor:StyleSetForeground(3, wx.wxColour(127, 127, 127)) -- Number editor:StyleSetForeground(4, wx.wxColour(0, 127, 127)) -- Keyword editor:StyleSetForeground(5, wx.wxColour(0, 0, 127)) -- Double quoted string editor:StyleSetBold(5, true) editor:StyleSetUnderline(5, false) editor:StyleSetForeground(6, wx.wxColour(127, 0, 127)) -- Single quoted string editor:StyleSetForeground(7, wx.wxColour(127, 0, 127)) -- not used editor:StyleSetForeground(8, wx.wxColour(0, 127, 127)) -- Literal strings editor:StyleSetForeground(9, wx.wxColour(127, 127, 0)) -- Preprocessor editor:StyleSetForeground(10, wx.wxColour(0, 0, 0)) -- Operators editor:StyleSetBold(10, true) editor:StyleSetForeground(11, wx.wxColour(0, 0, 0)) -- Identifiers editor:StyleSetForeground(12, wx.wxColour(0, 0, 0)) -- Unterminated strings editor:StyleSetBackground(12, wx.wxColour(224, 192, 224)) editor:StyleSetBold(12, true) editor:StyleSetEOLFilled(12, true) editor:StyleSetForeground(13, wx.wxColour(0, 0, 95)) -- Keyword highlighting styles editor:StyleSetForeground(14, wx.wxColour(0, 95, 0)) editor:StyleSetForeground(15, wx.wxColour(127, 0, 0)) editor:StyleSetForeground(16, wx.wxColour(127, 0, 95)) editor:StyleSetForeground(17, wx.wxColour(63, 95, 95)) editor:StyleSetForeground(18, wx.wxColour(0, 127, 127)) -- Nested literal strings ??? editor:StyleSetBackground(18, wx.wxColour(240,255,255)) editor:StyleSetForeground(19, wx.wxColour(0, 127, 127)) editor:StyleSetBackground(19, wx.wxColour(224,255,255)) editor:StyleSetForeground(20, wx.wxColour(0, 127, 127)) editor:StyleSetBackground(20, wx.wxColour(192,255,255)) editor:StyleSetForeground(21, wx.wxColour(0, 127, 127)) editor:StyleSetBackground(21, wx.wxColour(176,255,255)) editor:StyleSetForeground(22, wx.wxColour(0, 127, 127)) editor:StyleSetBackground(22, wx.wxColour(160,255,255)) editor:StyleSetForeground(23, wx.wxColour(0, 127, 127)) editor:StyleSetBackground(23, wx.wxColour(144,255,255)) editor:StyleSetForeground(24, wx.wxColour(0, 127, 127)) editor:StyleSetBackground(24, wx.wxColour(128,155,255)) editor:StyleSetForeground(32, wx.wxColour(224, 192, 224)) -- Line number editor:StyleSetBackground(33, wx.wxColour(192, 192, 192)) -- Brace highlight editor:StyleSetForeground(34, wx.wxColour(0, 0, 255)) editor:StyleSetBold(34, true) -- Brace incomplete highlight editor:StyleSetForeground(35, wx.wxColour(255, 0, 0)) editor:StyleSetBold(35, true) -- Indentation guides editor:StyleSetForeground(37, wx.wxColour(192, 192, 192)) editor:StyleSetBackground(37, wx.wxColour(255, 255, 255)) editor:SetUseTabs(false) editor:SetTabWidth(4) editor:SetIndent(4) editor:SetIndentationGuides(true) editor:SetMarginSensitive(1, true) editor:SetMarginWidth(1, 30) editor:SetMarginType(1, wxstc.wxSTC_MARGIN_NUMBER) editor:SetVisiblePolicy(wxstc.wxSTC_VISIBLE_SLOP, 3) editor:SetXCaretPolicy(wxstc.wxSTC_CARET_SLOP, 10) editor:SetYCaretPolicy(wxstc.wxSTC_CARET_SLOP, 3) editor:SetCaretLineVisible(true) editor:SetLexer(wxstc.wxSTC_LEX_LUA) editor:SetKeyWords(0, [[and break do else elseif end false for function if in local nil not or repeat return then true until while]]) editor:SetKeyWords(1, [[_PROMPT _VERSION _G _VERSION assert collectgarbage dofile error gcinfo getfenv getmetatable ipairs loadfile loadlib loadstring next pairs pcall print rawequal rawget rawset require setfenv setmetatable tonumber tostring type unpack xpcall]]) local Luakeywords = {} for i in pairs(math) do table.insert(Luakeywords, "math."..i.." ") end editor:SetKeyWords(2, table.concat(Luakeywords)) Luakeywords = {} for i in pairs(coroutine) do table.insert(Luakeywords, "coroutine."..i.." ") end for i in pairs(debug) do table.insert(Luakeywords, "debug."..i.." ") end for i in pairs(io) do table.insert(Luakeywords, "io."..i.." ") end for i in pairs(os) do table.insert(Luakeywords, "os."..i.." ") end for i in pairs(string) do table.insert(Luakeywords, "string."..i.." ") end for i in pairs(table) do table.insert(Luakeywords, "table."..i.." ") end editor:SetKeyWords(3, table.concat(Luakeywords)) -- editor:SetKeyWords(5, [[ -- ]]) -- editor:SetKeyWords(6, [[ -- ]]) editor:UsePopUp(false) parent:Connect(wx.wxID_ANY, wx.wxEVT_SIZE , function (event) editor:SetSize(parent:GetClientSize()) end) editor:Connect(wx.wxEVT_RIGHT_UP , function ( event ) editMenu = wx.wxMenu{ { wx.wxID_UNDO, "&Undo\tCtrl-Z", "Undo the last action" }, { wx.wxID_REDO, "&Redo\tCtrl-Y", "Redo the last action undone" }, { }, { wx.wxID_CUT, "Cu&t\tCtrl-X", "Deletes selected text and copies it to clipboard" }, { wx.wxID_COPY, "&Copy\tCtrl-C", "Copies selected text to the clipboard" }, { wx.wxID_PASTE, "&Paste\tCtrl-V", "Inserts clipboard contents at the current location" }, { wx.wxID_CLEAR, "D&elete\tDel", "Deletes selected text without copying to the clipboard" }, { wx.wxID_SELECTALL, "Select &All\tCtrl-A", "Select all text in the editor" }, { }, { wx.wxID_FIND, "&Find\tCtrl-F", "Find the specified text" }, { wxID_FINDNEXT, "Find &Next\tF3", "Find the next occurrence of the specified text" }, { wxID_FINDPREV, "Find &Previous\tShift-F3", "Repeat the search backwards in the file" }, { wxID_REPLACE, "&Replace\tCtrl-H", "Replaces the specified text with different text" }, { }, { wxID_GOTOLINE, "&Goto line\tCtrl-G", "Go to a selected line" } } editor:PopupMenu(editMenu, event:GetPosition()) end) editor:Connect(wx.wxEVT_KEY_DOWN, function(event) local keycode = event:GetKeyCode() local ctrl = event:ControlDown() local shift = event:ShiftDown() if shift and keycode==wx.WXK_F3 then local commandEvent = wx.wxCommandEvent(wx.wxEVT_COMMAND_MENU_SELECTED, wxID_FINDPREV) wx.wxPostEvent(editor, commandEvent) elseif keycode==wx.WXK_F3 then local commandEvent = wx.wxCommandEvent(wx.wxEVT_COMMAND_MENU_SELECTED, wxID_FINDNEXT) wx.wxPostEvent(editor, commandEvent) elseif ctrl and keycode==72 then local commandEvent = wx.wxCommandEvent(wx.wxEVT_COMMAND_MENU_SELECTED, wxID_REPLACE) wx.wxPostEvent(editor, commandEvent) elseif ctrl and keycode==70 then local commandEvent = wx.wxCommandEvent(wx.wxEVT_COMMAND_MENU_SELECTED, wx.wxID_FIND) wx.wxPostEvent(editor, commandEvent) elseif ctrl and keycode==71 then local commandEvent = wx.wxCommandEvent(wx.wxEVT_COMMAND_MENU_SELECTED, wxID_GOTOLINE) wx.wxPostEvent(editor, commandEvent) end event:Skip() end) editor:Connect(wx.wxID_UNDO, wx.wxEVT_COMMAND_MENU_SELECTED, function ( event ) editor:Undo() end) editor:Connect(wx.wxID_REDO, wx.wxEVT_COMMAND_MENU_SELECTED, function ( event ) editor:Redo() end) editor:Connect(wx.wxID_CUT, wx.wxEVT_COMMAND_MENU_SELECTED, function ( event ) editor:Cut() end) editor:Connect(wx.wxID_COPY, wx.wxEVT_COMMAND_MENU_SELECTED, function ( event ) editor:Copy() end) editor:Connect(wx.wxID_PASTE, wx.wxEVT_COMMAND_MENU_SELECTED, function ( event ) editor:Paste() end) editor:Connect(wx.wxID_CLEAR, wx.wxEVT_COMMAND_MENU_SELECTED, function ( event ) editor:Clear() end) editor:Connect(wx.wxID_SELECTALL, wx.wxEVT_COMMAND_MENU_SELECTED, function ( event ) editor:SelectAll() end) editor:Connect(wx.wxID_FIND, wx.wxEVT_COMMAND_MENU_SELECTED, function ( event ) findReplace(editor,false) end) editor:Connect(wxID_FINDNEXT, wx.wxEVT_COMMAND_MENU_SELECTED, function ( event ) if findData then findText(1, findData:GetFindString(), findData:GetFlags()) end end) editor:Connect(wxID_FINDPREV, wx.wxEVT_COMMAND_MENU_SELECTED, function ( event ) if findData then findText(2, findData:GetFindString(), findData:GetFlags()) end end) editor:Connect(wxID_REPLACE, wx.wxEVT_COMMAND_MENU_SELECTED, function ( event ) findReplace(editor,true) end) editor:Connect(wxID_GOTOLINE, wx.wxEVT_COMMAND_MENU_SELECTED, function ( event ) local linemax = editor:LineFromPosition(editor:GetLength()) + 1 local linenum = wx.wxGetNumberFromUser( "Enter line number", "1 .. "..tostring(linemax), "Goto Line", 1, 1, linemax, editor) if linenum > 0 then editor:GotoLine(linenum-1) end end) end function ensureRangeVisible(posStart, posEnd) if posStart > posEnd then posStart, posEnd = posEnd, posStart end local lineStart = editor:LineFromPosition(posStart) local lineEnd = editor:LineFromPosition(posEnd) for line = lineStart, lineEnd do editor:EnsureVisibleEnforcePolicy(line) end end function setSearchFlags(editor, fWholeWord, fMatchCase) local flags = 0 if fWholeWord then flags = wxstc.wxSTC_FIND_WHOLEWORD end if fMatchCase then flags = flags + wxstc.wxSTC_FIND_MATCHCASE end editor:SetSearchFlags(flags) end function findstring(strFind, fDown, fWholeWord, fMatchCase) local lenFind = string.len(strFind) if lenFind == 0 then return end local startSel = editor:GetSelectionStart() local endSel = editor:GetSelectionEnd() local startPosition = endSel local endPosition = editor:GetLength() if not fDown then startPosition = startSel - 1 endPosition = 0 end editor:SetTargetStart(startPosition) editor:SetTargetEnd(endPosition) setSearchFlags(editor, fWholeWord, fMatchCase) local posFind = editor:SearchInTarget(strFind) if posFind == -1 then if not fDown then startPosition = editor:GetLength() endPosition = 0 else startPosition = 0 endPosition = editor:GetLength() end editor:SetTargetStart(startPosition) editor:SetTargetEnd(endPosition) posFind = editor:SearchInTarget(strFind) end if posFind == -1 then fHaveFound = nil else fHaveFound = 1 local start = editor:GetTargetStart() local finish = editor:GetTargetEnd() ensureRangeVisible(start, finish) editor:SetSelection(start, finish) end end function replace(strFind, strReplace, fDown, fWholeWord, fMatchCase, fReplaceAll) local findLen = string.len(strFind) if findLen == 0 then return end if fReplaceAll then local startPosition = editor:GetSelectionStart() local endPosition = editor:GetLength() local replaceLen = string.len(strReplace) editor:SetTargetStart(startPosition) editor:SetTargetEnd(endPosition) setSearchFlags(editor, fWholeWord, fMatchCase) local posFind = editor:SearchInTarget(strFind) if (posFind ~= -1) and (posFind <= endPosition) then local lastMatch = posFind editor:BeginUndoAction() while posFind ~= -1 do local lenTarget = editor:GetTargetEnd() - editor:GetTargetStart() editor:ReplaceTarget(strReplace) endPosition = endPosition + replaceLen - lenTarget lastMatch = posFind + replaceLen if lenTarget <= 0 then lastMatch = lastMatch + 1 end editor:SetTargetStart(lastMatch) editor:SetTargetEnd(endPosition) posFind = editor:SearchInTarget(strFind) end editor:SetSelection(lastMatch, lastMatch) editor:EndUndoAction() end else if fHaveFound then local replaceLen = string.len(strReplace) local start = editor:GetSelectionStart() local finish = editor:GetSelectionEnd() editor:SetTargetStart(start) editor:SetTargetEnd(finish) editor:ReplaceTarget(strReplace) editor:SetSelection(start + replaceLen, finish) fHaveFound = nil end findstring(strFind, fDown, fWholeWord, fMatchCase) end end function findText(where, strFind, findFlags) -- where == 2 - Find previous -- where == 1 - Find next -- where == 0 or where == nil - Find local fDown, fWholeWord, fMatchCase if findFlags >= wx.wxFR_MATCHCASE then findFlags = findFlags - wx.wxFR_MATCHCASE fMatchCase = 1 end if findFlags >= wx.wxFR_WHOLEWORD then findFlags = findFlags - wx.wxFR_WHOLEWORD fWholeWord = 1 end if findFlags >= wx.wxFR_DOWN and where ~= 2 then fDown = 1 end findstring(strFind, fDown, fWholeWord, fMatchCase) end function replaceText(where, strFind, strReplace, findFlags) -- where == 1 - Replace all -- where == 0 - Replace local fDown, fWholeWord, fMatchCase if findFlags >= wx.wxFR_MATCHCASE then findFlags = findFlags - wx.wxFR_MATCHCASE fMatchCase = 1 end if findFlags >= wx.wxFR_WHOLEWORD then findFlags = findFlags - wx.wxFR_WHOLEWORD fWholeWord = 1 end if findFlags >= wx.wxFR_DOWN and where ~= 2 then fDown = 1 end replace(strFind, strReplace, fDown, fWholeWord, fMatchCase, where == 1) end function findReplace(editor,replace) if not findData then findData = wx.wxFindReplaceData(wx.wxFR_DOWN) end local flag local title if replace then flag = wx.wxFR_REPLACEDIALOG title = "Replace" else flag = 0 title = "Find" end if not finddlg then finddlg = wx.wxFindReplaceDialog(editor, findData, title, flag) finddlg:Connect(wx.wxEVT_COMMAND_FIND, function ( event ) findText(0, event:GetFindString(), event:GetFlags()) end) finddlg:Connect(wx.wxEVT_COMMAND_FIND_NEXT, function ( event ) findText(1, event:GetFindString(), event:GetFlags()) end) finddlg:Connect(wx.wxEVT_COMMAND_FIND_REPLACE, function ( event ) replaceText(0, event:GetFindString(), event:GetReplaceString(), event:GetFlags()) end) finddlg:Connect(wx.wxEVT_COMMAND_FIND_REPLACE_ALL, function ( event ) replaceText(1, event:GetFindString(), event:GetReplaceString(), event:GetFlags()) end) finddlg:Connect(wx.wxEVT_COMMAND_FIND_CLOSE, function ( event ) finddlg:Destroy() finddlg = nil end) finddlg:Show(true) end end function loadEditor(parent,filePath) if editor ~= nil then editor:Destroy() editor = nil end createEditor(parent) local handle = io.open(filePath, "rb") if handle then local st = handle:read("*a") handle:close() editor:Clear() editor:ClearAll() editor:InsertText(0, st) editor:EmptyUndoBuffer() end return editor end function saveEditor(filePath) local saved = false local st = editor:GetText() local handle = io.open(filePath, "wb") if handle then handle:write(st) handle:close() editor:EmptyUndoBuffer() saved = true end return saved end function getTextEditor() local st = "" if editor then st = editor:GetText() end return st end