(* Copyright 2021 Anton Krotov This file is part of CEdit. CEdit is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. CEdit is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with CEdit. If not, see . *) MODULE CEdit; IMPORT OpenDlg, K := KolibriOS, U := Utils, Lines, Menu, List, G := Graph, T := Text, E := Encodings, CB := Clipboard, Languages, ChangeLog, Scroll, CheckBox, RW, Ini, EB := EditBox, Icons, Tabs, Timer; CONST HEADER = "CEdit (08-dec-2021)"; ShellFilter = ""; EditFilter = "SH|INC|TXT|ASM|OB07|C|CPP|H|PAS|PP|LUA|INI|JSON"; fontWidth = K.fontWidth; fontHeight = K.fontHeight; scrollWidth = 22; btnClose = 1; btnNew = 20; btnOpen = 21; btnSave = 22; btnSearch = 23; btnUndo = 24; btnRedo = 25; btnUpper = 26; btnLower = 27; btnBuild = 28; btnRun = 29; btnYes = 40; btnNo = 41; btnFindNext = 42; btnReplace = 43; btnReplaceAll = 44; btnGoto = 45; btnCloseSearch = 46; btnHideSearch = 47; mainMenuBtn = 60; btnHeight = 25; btnWidth = 75; btnTop = Menu.MainMenuHeight + 3; toolBtnSize = 24; toolbarDelim = 7; iconPad = (toolBtnSize - Icons.SIZE) DIV 2; TOP = btnTop + toolBtnSize + 10 + Tabs.tabHeight; RIGHT = scrollWidth - 2; BOTTOM = scrollWidth + 18; minWinWidth = 635; minWinHeight = 550; SEARCH_PADDING = 10; searchLeft = 0; EditBox_Width = 180; EDITBOX_MAXCHARS = 500; menuFileX = searchLeft; menuEditX = menuFileX + 4*fontWidth + 9; menuSearchX = menuEditX + 4*fontWidth + 9; menuEncodingX = menuSearchX + 6*fontWidth + 9; menuViewX = menuEncodingX + 8*fontWidth + 9; menuLanguageX = menuViewX + 4*fontWidth + 9; menuProgramX = menuLanguageX + 8*fontWidth + 9; menuToolsX = menuProgramX + 7*fontWidth + 9; menuCut = 1; menuCopy = 2; menuPaste = 3; menuDelete = 4; menuSelectAll = 5; menuUndo = 6; menuRedo = 7; menuCurLine = 100; menuIndent = 110; menuCase = 120; menuNew = 10; menuOpen = 11; menuSave = 12; menuSaveAs = 13; menuSaveAll = 14; menuFolder = 15; menuClose = 16; menuExit = 17; menuNumbers = 20; menuFontSize = 21; menuColors = 1000; menuMaxColors = menuColors + Ini.MAX_SECTIONS - 1; menuText = 30; menuC = 31; menuFasm = 32; menuIni = 33; menuJSON = 34; menuLua = 35; menuOberon = 36; menuPascal = 37; menuBuild = 50; menuBuildScript = 51; menuRun = 52; menuRunScript = 53; menuDebug = 54; menuDebugScript = 55; menuUTF8BOM = 60; menuUTF8 = 61; menuCP866 = 62; menuWin1251 = 63; menuEOL = 140; menuPipet = 70; menuBoard = 71; menuSysFunc = 72; menuFind = 80; menuFindNext = 81; menuFindPrev = 82; menuGoto = 83; menuBookmark = 130; menuMoveUp = 101; menuMoveDown = 102; menuDuplicate = 103; menuRemove = 104; menuIncInd = 111; menuDecInd = 112; menuUpper = 121; menuLower = 122; menuToggleBookmark = 131; menuNextBookmark = 132; menuPrevBookmark = 133; menuLF = 141; menuCRLF = 142; menuCR = 143; maxTexts = 32; VAR canvas: G.tCanvas; font, font1, font2: G.tFont; tabs: Tabs.tTabs; text: T.tText; texts: ARRAY maxTexts OF T.tText; textsCount, curText: INTEGER; winWidth, winHeight: INTEGER; AppPath, runScript, buildScript, debugScript: RW.tFileName; OD: OpenDlg.Dialog; confirm, notFound, menuFindClicked, search, searchOpened, modified: BOOLEAN; eol, enc: INTEGER; switch, closing: BOOLEAN; leftButton: BOOLEAN; LEFT: INTEGER; FindEdit, ReplaceEdit, GotoEdit: EB.tEditBox; hScroll, vScroll: Scroll.tScroll; CS, WH, BKW: CheckBox.tCheckBox; new_searchText, searchText, replaceText, gotoText: T.tString; cs, whole: BOOLEAN; replaced: INTEGER; mainTID: INTEGER; context, menuFile, menuEdit, menuSearch, menuEncoding, menuView, menuLanguage, menuProgram, menuTools, subCurLine, subIndent, subCase, subBookmark, subEOL: Menu.tMenu; mainMenu: Menu.tMain; menuActive: BOOLEAN; icons: INTEGER; grayIcons: INTEGER; IPC: ARRAY 64 OF INTEGER; PROCEDURE WritePos (y: INTEGER); VAR s1, s2: ARRAY 32 OF WCHAR; line, col: INTEGER; BEGIN T.getPos(text, col, line); U.int2str(line, s1); U.int2str(col, s2); U.append(s1, ": "); U.append(s1, s2); K.DrawText(LEFT, y, K.textColor, s1) END WritePos; PROCEDURE EditBox_Focus (edit: EB.tEditBox): BOOLEAN; RETURN 1 IN edit.flags END EditBox_Focus; PROCEDURE resetTimer; BEGIN IF EditBox_Focus(FindEdit) OR EditBox_Focus(ReplaceEdit) OR EditBox_Focus(GotoEdit) THEN T.hideCursor; Timer.kill ELSE T.showCursor; Timer.create(mainTID) END END resetTimer; PROCEDURE EditBox_SetFocus (VAR edit: EB.tEditBox; value: BOOLEAN); BEGIN IF value THEN INCL(edit.flags, 1) ELSE EXCL(edit.flags, 1) END; IF search & searchOpened THEN EB.paint(edit) END END EditBox_SetFocus; PROCEDURE SetFocus (VAR edit: EB.tEditBox; value: BOOLEAN); BEGIN EditBox_SetFocus(FindEdit, FALSE); EditBox_SetFocus(ReplaceEdit, FALSE); EditBox_SetFocus(GotoEdit, FALSE); EditBox_SetFocus(edit, value); resetTimer END SetFocus; PROCEDURE Rect (left, top, right, bottom, color: INTEGER); BEGIN K.DrawLine(left, top, right, top, color); K.DrawLine(left, bottom, right, bottom, color); K.DrawLine(left, top, left, bottom, color); K.DrawLine(right, top, right, bottom, color); END Rect; PROCEDURE Message (s: ARRAY OF WCHAR); CONST minWidth = 30; height = 40; borderColor = 808080H; VAR top, left, right, bottom, x, y, width: INTEGER; BEGIN Timer.kill; width := minWidth + LENGTH(s)*fontWidth; left := (canvas.width - width) DIV 2 + LEFT; top := (canvas.height - height) DIV 2 + TOP; bottom := top + height - 1; right := left + width - 1; x := minWidth DIV 2 + left; y := (height - fontHeight) DIV 2 + top; K.DrawRect(left, top, width, height, K.winColor); Rect(left, top, right, bottom, borderColor); K.DrawText(x, y, K.textColor, s); END Message; PROCEDURE NotFound; BEGIN IF notFound THEN Message("not found"); IF menuFindClicked THEN menuFindClicked := FALSE ELSE notFound := FALSE END; SetFocus(FindEdit, TRUE) END END NotFound; PROCEDURE Replaced; VAR s, s1: ARRAY 32 OF WCHAR; BEGIN IF replaced # 0 THEN s := "replaced: "; U.int2str(replaced, s1); U.append(s, s1); Message(s); replaced := 0; SetFocus(FindEdit, TRUE) END END Replaced; PROCEDURE drawIcon (icons, idx, x: INTEGER); BEGIN Icons.draw(icons, idx, x + iconPad, btnTop + iconPad) END drawIcon; PROCEDURE toolbarIcons; VAR x, color, ico: INTEGER; BEGIN x := searchLeft + (toolBtnSize + 5)*2; IF text.modified THEN ico := icons ELSE ico := grayIcons END; drawIcon(ico, 5, x); IF text.edition # NIL THEN x := searchLeft + (toolBtnSize + 5)*4 + toolbarDelim*2; IF ChangeLog.isFirstGuard(text.edition) THEN ico := grayIcons ELSE ico := icons END; drawIcon(ico, 37, x); x := searchLeft + (toolBtnSize + 5)*5 + toolbarDelim*2; IF ChangeLog.isLastGuard(text.edition) THEN ico := grayIcons ELSE ico := icons END; drawIcon(ico, 36, x) END; IF T.selected(text) THEN color := K.caseColor ELSE color := K.disCaseColor END; x := searchLeft + (toolBtnSize + 5)*6 + toolbarDelim*3; K.DrawRect(x, btnTop, toolBtnSize, toolBtnSize, K.toolbarColor); K.DrawText69(x + (toolBtnSize - 12) DIV 2, btnTop + (toolBtnSize - 9) DIV 2 + 2, color, "AB"); INC(x, toolBtnSize + 5); K.DrawRect(x, btnTop, toolBtnSize, toolBtnSize, K.toolbarColor); K.DrawText69(x + (toolBtnSize - 12) DIV 2, btnTop + (toolBtnSize - 9) DIV 2 + 2, color, "ab"); x := searchLeft + (toolBtnSize + 5)*8 + toolbarDelim*4; IF buildScript # "" THEN ico := icons ELSE ico := grayIcons END; drawIcon(ico, 54, x); INC(x, toolBtnSize + 5); IF runScript # "" THEN ico := icons ELSE ico := grayIcons END; drawIcon(ico, 53, x) END toolbarIcons; PROCEDURE getIdx (text: T.tText): INTEGER; VAR i: INTEGER; BEGIN i := 0; WHILE texts[i] # text DO INC(i) END RETURN i END getIdx; PROCEDURE MarkModified; BEGIN modified := text.modified; Tabs.modify(tabs, getIdx(text), modified) END MarkModified; PROCEDURE SetCaption (fileName: RW.tFileName); VAR header: RW.tFileName; BEGIN header := HEADER; IF text.fileName # "" THEN U.append8(header, " - "); U.append8(header, text.fileName) END; K.SetCaption(header) END SetCaption; PROCEDURE DrawState (text: T.tText; width, height: INTEGER); VAR y: INTEGER; s: ARRAY 24 OF WCHAR; BEGIN eol := T.getEol(text); enc := T.getEnc(text); s := ""; U.append(s, RW.eolNames[eol]); U.append(s, 20X + 20X); U.append(s, E.names[enc]); SetCaption(text.fileName); K.DrawRect(LEFT + 16*fontWidth, TOP + canvas.height + scrollWidth, width - (LEFT + 16*fontWidth), BOTTOM - scrollWidth + 1, K.winColor); y := height - (BOTTOM - scrollWidth) + (BOTTOM - scrollWidth - 16) DIV 2; K.DrawText(width - LENGTH(s)*fontWidth, y, K.textColor, s); MarkModified END DrawState; PROCEDURE DrawScroll (VAR scroll: Scroll.tScroll; left, top, value, maxVal: INTEGER); BEGIN scroll.maxVal := maxVal; scroll.left := left; scroll.top := top; Scroll.setValue(scroll, value); Scroll.paint(scroll) END DrawScroll; PROCEDURE repaint; VAR width, height, scrollX, scrollY, y: INTEGER; BEGIN IF text # NIL THEN IF confirm THEN K.DeleteButton(btnYes); K.DeleteButton(btnNo); confirm := FALSE; resetTimer; closing := FALSE END; IF ~search OR (searchText = "") THEN T.wordSel(text) END; K.ClientSize(width, height); IF switch THEN DrawState(text, width, height); Tabs.draw(tabs); IF search & T.search(text, searchText, cs, whole) THEN END; switch := FALSE END; T.draw(text); y := height - (BOTTOM - scrollWidth) + (BOTTOM - scrollWidth - 16) DIV 2; K.DrawRect(LEFT, TOP + canvas.height + scrollWidth, 16*fontWidth, BOTTOM - scrollWidth + 1, K.winColor); WritePos(y); IF (enc # T.getEnc(text)) OR (eol # T.getEol(text)) THEN DrawState(text, width, height) ELSIF modified # text.modified THEN MarkModified END; T.getScroll(text, scrollX, scrollY); DrawScroll(vScroll, LEFT + canvas.width, TOP - 1, scrollY, text.count - 1); DrawScroll(hScroll, LEFT, TOP + canvas.height, scrollX, text.maxLength); IF search & searchOpened THEN CheckBox.paint(BKW); CheckBox.paint(CS); CheckBox.paint(WH); END; G.DrawCanvas(canvas, LEFT, TOP); NotFound; Replaced; toolbarIcons END END repaint; PROCEDURE resize; VAR cliWidth, cliHeight: INTEGER; BEGIN K.WinSize(winWidth, winHeight); IF winWidth < minWinWidth THEN winWidth := minWinWidth END; IF winHeight < minWinHeight THEN winHeight := minWinHeight END; K.SetWinSize(winWidth, winHeight); K.WinSize(winWidth, winHeight); K.ClientSize(cliWidth, cliHeight); G.destroy(canvas); canvas := G.CreateCanvas(cliWidth - (LEFT + RIGHT + 2), cliHeight - (TOP + BOTTOM + 1)); Tabs.setArea(tabs, LEFT, TOP - Tabs.tabHeight, cliWidth - (LEFT + RIGHT + 2), Tabs.tabHeight); G.SetFont(canvas, font); T.setCanvas(canvas); T.resize(canvas.width, canvas.height); Scroll.resize(vScroll, vScroll.width, canvas.height + 2); Scroll.resize(hScroll, canvas.width + 1, hScroll.height); END resize; PROCEDURE SearchPanel (left, top: INTEGER); VAR y, right, bottom, color: INTEGER; BEGIN DEC(top, Tabs.tabHeight); right := left + EditBox_Width + SEARCH_PADDING*2; bottom := top + 395 + btnHeight + SEARCH_PADDING; color := K.borderColor; Rect(left, top, right, bottom, color); K.CreateButton(btnCloseSearch, right - 20, top, 20, 20, 0EF999FH, ""); K.DrawLine(right - 14, top + 5, right - 5, top + 14, 0FFFFFFH); K.DrawLine(right - 15, top + 5, right - 5, top + 15, 0FFFFFFH); K.DrawLine(right - 15, top + 6, right - 6, top + 15, 0FFFFFFH); K.DrawLine(right - 15, top + 14, right - 6, top + 5, 0FFFFFFH); K.DrawLine(right - 15, top + 15, right - 5, top + 5, 0FFFFFFH); K.DrawLine(right - 14, top + 15, right - 5, top + 6, 0FFFFFFH); K.CreateButton(btnHideSearch, right - 40, top, 20, 20, K.btnColor, ""); K.DrawLine(right - 34, top + 14, right - 26, top + 14, K.btnTextColor); K.DrawLine(right - 34, top + 15, right - 26, top + 15, K.btnTextColor); INC(top, 15); INC(left, SEARCH_PADDING); K.DrawText866(left, top, K.textColor, "find"); K.DrawText866(left, top + 55, K.textColor, "replace with"); K.DrawText866(left, top + 330, K.textColor, "go to line"); BKW.top := top + 110; BKW.left := left; CS.top := top + 140; CS.left := left; WH.top := top + 170; WH.left := left; FindEdit.top := top + 20; ReplaceEdit.top := top + 75; GotoEdit.top := top + 350; FindEdit.left := left; ReplaceEdit.left := left; GotoEdit.left := left; EB.paint(FindEdit); EB.paint(ReplaceEdit); EB.paint(GotoEdit); y := top + 200; K.CreateButton(btnFindNext, left, y, btnWidth, btnHeight, K.btnColor, "next"); INC(y, btnHeight + 10); K.CreateButton(btnReplace, left, y, btnWidth, btnHeight, K.btnColor, "replace"); INC(y, btnHeight + 10); K.CreateButton(btnReplaceAll, left, y, btnWidth + 5*fontWidth - 2, btnHeight, K.btnColor, "replace all"); K.CreateButton(btnGoto, left, top + 380, btnWidth, btnHeight, K.btnColor, "go"); END SearchPanel; PROCEDURE draw_window; VAR width, height, x: INTEGER; PROCEDURE drawToolbarBtn (id, x: INTEGER); BEGIN K.DrawRect(x, btnTop, toolBtnSize, toolBtnSize, K.toolbarColor); K.DrawLine(x, btnTop + toolBtnSize, x + toolBtnSize, btnTop + toolBtnSize, K.shadowColor); K.DrawLine(x + toolBtnSize, btnTop, x + toolBtnSize, btnTop + toolBtnSize, K.shadowColor); K.CreateButton(id + ORD({30}), x, btnTop, toolBtnSize, toolBtnSize, K.btnColor, ""); END drawToolbarBtn; BEGIN K.BeginDraw; K.CreateWindow(30 + K.GetTickCount() MOD 128, 30 + K.GetTickCount() MOD 128, winWidth, winHeight, K.winColor, 73H, 0, 0, ""); IF (text # NIL) & ~K.RolledUp() THEN IF confirm THEN resetTimer END; confirm := FALSE; K.ClientSize(width, height); K.DrawRect(0, 0, width, TOP, K.winColor); K.DrawRect(0, 0, LEFT, height, K.winColor); K.DrawRect(LEFT + canvas.width + 1, TOP + canvas.height, scrollWidth - 1, scrollWidth, K.winColor); Menu.DrawMain(mainMenu); x := searchLeft; drawToolbarBtn(btnNew, x); drawIcon(icons, 2, x); INC(x, toolBtnSize + 5); drawToolbarBtn(btnOpen, x); drawIcon(icons, 0, x); INC(x, toolBtnSize + 5); drawToolbarBtn(btnSave, x); INC(x, toolBtnSize + 5 + toolbarDelim); drawToolbarBtn(btnSearch, x); drawIcon(icons, 49, x); INC(x, toolBtnSize + 5 + toolbarDelim); drawToolbarBtn(btnUndo, x); INC(x, toolBtnSize + 5); drawToolbarBtn(btnRedo, x); INC(x, toolBtnSize + 5 + toolbarDelim); drawToolbarBtn(btnUpper, x); INC(x, toolBtnSize + 5); drawToolbarBtn(btnLower, x); INC(x, toolBtnSize + 5 + toolbarDelim); drawToolbarBtn(btnBuild, x); INC(x, toolBtnSize + 5); drawToolbarBtn(btnRun, x); INC(x, toolBtnSize + 5); toolbarIcons; DrawState(text, width, height); IF search & searchOpened THEN SearchPanel(searchLeft, TOP) END; Tabs.draw(tabs); repaint END; K.EndDraw END draw_window; PROCEDURE mouse (VAR x, y: INTEGER); VAR msState: SET; BEGIN K.mouse(msState, x, y); DEC(x, LEFT); DEC(y, TOP) END mouse; PROCEDURE stopTimer; BEGIN T.hideCursor; Timer.kill; repaint END stopTimer; PROCEDURE OpenFile (VAR FileName: RW.tFileName; filter: ARRAY OF CHAR); BEGIN stopTimer; OpenDlg.SetFilter(OD, filter); OpenDlg.Show(OD, 500, 400); WHILE OD.status = 2 DO K.Pause(30) END; IF OD.status = 1 THEN COPY(OD.FilePath, FileName) ELSE FileName := "" END; resetTimer END OpenFile; PROCEDURE error (s: RW.tFileName); VAR temp: RW.tFileName; BEGIN temp := "'CEdit: "; U.append8(temp, s); U.append8(temp, "' -E"); K.Run("/rd/1/@notify", temp) END error; PROCEDURE saveError (name: RW.tFileName); VAR s: RW.tFileName; BEGIN s := "error saving file "; U.append8(s, name); error(s) END saveError; PROCEDURE saveAs (text: T.tText); VAR fileName, name: RW.tFileName; ext: ARRAY 8 OF CHAR; BEGIN OD._type := OpenDlg.tsave; U.getFileName(text.fileName, OD.FileName, U.SLASH); IF OD.FileName = "" THEN OD.FileName := "NewFile."; Languages.getExt(text.lang, ext); U.append8(OD.FileName, ext) END; OpenFile(fileName, EditFilter); IF fileName # "" THEN IF T.save(text, fileName) THEN T.setName(text, fileName); U.getFileName(fileName, name, U.SLASH); Tabs.rename(tabs, curText, name) ELSE saveError(fileName) END END END saveAs; PROCEDURE Switch (txt: T.tText); BEGIN Tabs.switch(tabs, curText); text := txt; T.switch(txt); switch := TRUE END Switch; PROCEDURE save (text: T.tText); BEGIN IF text.modified THEN IF text.fileName # "" THEN IF ~T.save(text, text.fileName) THEN saveError(text.fileName) END ELSE curText := getIdx(text); Switch(text); saveAs(text) END; Tabs.modify(tabs, getIdx(text), text.modified) END END save; PROCEDURE saveAll; VAR i: INTEGER; txt: T.tText; BEGIN i := textsCount - 1; WHILE i >= 0 DO txt := texts[i]; IF txt.modified THEN T.switch(txt); save(txt) END; DEC(i) END; T.switch(text) END saveAll; PROCEDURE insert (pos: INTEGER; txt: T.tText); VAR i: INTEGER; name: RW.tFileName; BEGIN FOR i := textsCount - 1 TO pos BY -1 DO texts[i + 1] := texts[i] END; texts[pos] := txt; INC(textsCount); curText := pos; IF txt.fileName = "" THEN name := "new" ELSE U.getFileName(txt.fileName, name, U.SLASH) END; Tabs.add(tabs, name); Switch(txt) END insert; PROCEDURE Confirm; CONST width = btnWidth*2 + 30; height = btnHeight*2 + 20; lineColor = 808080H; VAR left, top, right, bottom: INTEGER; BEGIN stopTimer; draw_window; confirm := TRUE; left := (canvas.width - width) DIV 2 + LEFT; top := (canvas.height - height) DIV 2 + TOP; right := left + width - 1; bottom := top + height - 1; K.DrawRect(left, top, width, height, K.winColor); Rect(left, top, right, bottom, lineColor); K.DrawText866(left + (width - 10*fontWidth) DIV 2, top + 10, K.textColor, "save file?"); K.CreateButton(btnYes, left + 10, top + 35, btnWidth, btnHeight, K.btnColor, "yes"); K.CreateButton(btnNo, left + 20 + btnWidth, top + 35, btnWidth, btnHeight, K.btnColor, "no"); END Confirm; PROCEDURE closeFile (conf: BOOLEAN; n: INTEGER); VAR i: INTEGER; BEGIN IF texts[n].modified & conf THEN Confirm ELSE Tabs.delete(tabs, n); FOR i := n + 1 TO textsCount - 1 DO texts[i - 1] := texts[i] END; DEC(textsCount); IF (curText = textsCount) OR (n < curText) THEN DEC(curText) END; IF curText >= 0 THEN Switch(texts[curText]) ELSE K.Exit END; draw_window END END closeFile; PROCEDURE NewFile; VAR nov: T.tText; BEGIN IF textsCount < maxTexts THEN nov := T.New(); T.SetPos(nov, 0, 0); insert(textsCount, nov) ELSE error("too many files") END END NewFile; PROCEDURE getFileNum (fileName: RW.tFileName): INTEGER; VAR i: INTEGER; PROCEDURE nameEq (name1, name2: RW.tFileName): BOOLEAN; VAR n1, n2: RW.tFileName; BEGIN n1 := name1; n2 := name2; U.upcase(n1); U.upcase(n2) RETURN n1 = n2 END nameEq; BEGIN i := 0; WHILE (i < textsCount) & ~nameEq(texts[i].fileName, fileName) DO INC(i) END; IF i = textsCount THEN i := -1 END RETURN i END getFileNum; PROCEDURE SwitchTab (n: INTEGER); BEGIN curText := n; Tabs.switch(tabs, n); Switch(texts[n]); resetTimer; draw_window END SwitchTab; PROCEDURE open; VAR fileName: RW.tFileName; nov: T.tText; err, n: INTEGER; BEGIN IF textsCount < maxTexts THEN OD._type := OpenDlg.topen; OpenFile(fileName, EditFilter); IF fileName # "" THEN n := getFileNum(fileName); IF n = -1 THEN nov := T.open(fileName, err); IF nov = NIL THEN error("error opening file") ELSE insert(textsCount, nov); T.SetPos(nov, 0, 0) END ELSE SwitchTab(n) END END ELSE error("too many files") END END open; PROCEDURE createSearchForm; BEGIN EB.create(searchLeft, TOP + 20, EditBox_Width, EDITBOX_MAXCHARS, FindEdit); EB.create(searchLeft, TOP + 20 + 55, EditBox_Width, EDITBOX_MAXCHARS, ReplaceEdit); EB.create(searchLeft, TOP + 20 + 330, EditBox_Width, EDITBOX_MAXCHARS, GotoEdit); INCL(GotoEdit.flags, 15); CheckBox.create("backward", BKW); CheckBox.create("match case", CS); CheckBox.create("whole word", WH); END createSearchForm; PROCEDURE EditBox_GetValue (edit: EB.tEditBox; VAR s: ARRAY OF WCHAR); VAR str: ARRAY EDITBOX_MAXCHARS + 1 OF CHAR; i: INTEGER; BEGIN EB.getValue(edit, str); i := 0; WHILE str[i] # 0X DO s[i] := WCHR(E.cp866[ORD(str[i])]); INC(i) END; s[i] := 0X END EditBox_GetValue; PROCEDURE Search; BEGIN search := ~search; LEFT := searchLeft; IF search THEN searchOpened := TRUE; INC(LEFT, EditBox_Width + SEARCH_PADDING*2 + 5); IF T.search(text, searchText, cs, whole) THEN END ELSE IF T.search(text, "", FALSE, FALSE) THEN END END; SetFocus(FindEdit, search); resize; draw_window END Search; PROCEDURE click (x, y: INTEGER): INTEGER; VAR scrollX, scrollY: INTEGER; shift, ctrl: BOOLEAN; BEGIN K.getKBState(shift, ctrl); T.getScroll(text, scrollX, scrollY); T.scroll(text, hScroll.value - scrollX, vScroll.value - scrollY); IF U.between(0, x, canvas.width - 1) & U.between(0, y, canvas.height - 1) THEN leftButton := TRUE; SetFocus(FindEdit, FALSE); IF ~shift THEN T.resetSelect(text) END; T.mouse(text, x, y) END; repaint RETURN K.GetTickCount() END click; PROCEDURE Close; VAR cont: BOOLEAN; BEGIN closing := TRUE; cont := TRUE; WHILE (textsCount > 0) & cont DO IF text.modified THEN Confirm; cont := FALSE ELSE closeFile(FALSE, curText); repaint END END END Close; PROCEDURE CloseMenu; BEGIN Menu.close(subEOL); Menu.close(subCurLine); Menu.close(subIndent); Menu.close(subCase); Menu.close(subBookmark); Menu.close(menuFile); Menu.close(menuEdit); Menu.close(menuSearch); Menu.close(menuEncoding); Menu.close(menuView); Menu.close(menuLanguage); Menu.close(menuProgram); Menu.close(menuTools); Menu.close(context) END CloseMenu; PROCEDURE MenuItemClick (menu: Menu.tMenu; id: INTEGER); VAR msg: ARRAY 2 OF INTEGER; BEGIN msg[0] := id; msg[1] := 8; K.SendIPC(mainTID, msg) END MenuItemClick; PROCEDURE goto; VAR gotoVal: INTEGER; BEGIN EditBox_GetValue(GotoEdit, gotoText); IF U.str2int(gotoText, gotoVal) & T.goto(text, gotoVal) THEN SetFocus(GotoEdit, FALSE) END END goto; PROCEDURE Script (script: ARRAY OF CHAR); BEGIN IF script # "" THEN K.Run("/rd/1/@open", script) END END Script; PROCEDURE ShowSearchPanel (goto: BOOLEAN); VAR i: INTEGER; (*flag: BOOLEAN;*) BEGIN (*flag := FALSE;*) IF T.selected(text) & ~goto THEN T.getSelectedText(text, new_searchText); IF new_searchText # "" THEN i := 0; WHILE (new_searchText[i] # 0X) & (new_searchText[i] # Lines.TAB) DO INC(i) END; IF new_searchText[i] = 0X THEN searchText := new_searchText; EB.setValue(FindEdit, searchText); notFound := ~T.search(text, searchText, cs, whole); (*flag := TRUE*) END END END; IF ~search THEN Search ELSIF ~searchOpened THEN search := FALSE; Search END; IF goto THEN SetFocus(GotoEdit, TRUE) ELSE SetFocus(FindEdit, (*~flag*)TRUE) END END ShowSearchPanel; PROCEDURE CanvasToScreen (VAR x, y: INTEGER); VAR cliX, cliY, winX, winY: INTEGER; BEGIN K.WinPos(winX, winY); K.ClientPos(cliX, cliY); x := x + winX + cliX + LEFT; y := y + winY + cliY + TOP; END CanvasToScreen; PROCEDURE ShowMenu (menu: Menu.tMenu); VAR winX, winY, cliX, cliY, x, y, i: INTEGER; selected, enabled: BOOLEAN; BEGIN IF menu = context THEN mouse(x, y); IF ~(U.between(0, x, canvas.width - 1) & U.between(0, y, canvas.height - 1)) THEN menu := NIL END ELSE K.WinPos(winX, winY); K.ClientPos(cliX, cliY); x := winX + cliX; y := Menu.MainMenuHeight + winY + cliY END; selected := T.selected(text); IF menu = menuFile THEN Menu.setEnabled(menu, menuSave, text.modified); Menu.setEnabled(menu, menuFolder, text.fileName # ""); i := 0; WHILE (i < textsCount) & ~texts[i].modified DO INC(i) END; Menu.setEnabled(menu, menuSaveAll, i < textsCount); INC(x, menuFileX) ELSIF (menu = menuEdit) OR (menu = context) THEN Menu.setEnabled(menu, menuUndo, ~ChangeLog.isFirstGuard(text.edition)); Menu.setEnabled(menu, menuRedo, ~ChangeLog.isLastGuard(text.edition)); Menu.setEnabled(menu, menuCut, selected); Menu.setEnabled(menu, menuCopy, selected); Menu.setEnabled(menu, menuDelete, selected); Menu.setEnabled(menu, menuPaste, CB.available()); IF menu = menuEdit THEN INC(x, menuEditX) ELSE IF y + menu.height >= canvas.height THEN DEC(y, menu.height) END; IF x + menu.width >= canvas.width THEN DEC(x, menu.width) END; CanvasToScreen(x, y) END ELSIF menu = menuEncoding THEN Menu.option(menu, menuUTF8BOM, T.getEnc(text) = E.UTF8BOM); Menu.option(menu, menuUTF8, T.getEnc(text) = E.UTF8); Menu.option(menu, menuCP866, T.getEnc(text) = E.CP866); Menu.option(menu, menuWin1251, T.getEnc(text) = E.W1251); INC(x, menuEncodingX) ELSIF menu = menuView THEN Menu.check(menu, menuNumbers, text.numbers); Menu.check(menu, menuFontSize, font = font2); FOR i := 0 TO Ini.sections.count - 1 DO Menu.option(menu, menuColors + i, Ini.curSectionNum = i) END; INC(x, menuViewX) ELSIF menu = menuLanguage THEN Menu.option(menu, menuText, text.lang = Languages.langText); Menu.option(menu, menuC, text.lang = Languages.langC); Menu.option(menu, menuFasm, text.lang = Languages.langFasm); Menu.option(menu, menuIni, text.lang = Languages.langIni); Menu.option(menu, menuJSON, text.lang = Languages.langJSON); Menu.option(menu, menuLua, text.lang = Languages.langLua); Menu.option(menu, menuOberon, text.lang = Languages.langOberon); Menu.option(menu, menuPascal, text.lang = Languages.langPascal); INC(x, menuLanguageX) ELSIF menu = menuProgram THEN Menu.setEnabled(menu, menuBuild, buildScript # ""); Menu.setEnabled(menu, menuDebug, debugScript # ""); Menu.setEnabled(menu, menuRun, runScript # ""); INC(x, menuProgramX) ELSIF menu = menuTools THEN INC(x, menuToolsX) ELSIF menu = menuSearch THEN INC(x, menuSearchX) END; enabled := search & (searchText # ""); Menu.setEnabled(menuSearch, menuFindNext, enabled); Menu.setEnabled(menuSearch, menuFindPrev, enabled); Menu.setEnabled(subIndent, menuIncInd, selected); Menu.setEnabled(subIndent, menuDecInd, selected); Menu.setEnabled(subCase, menuUpper, selected); Menu.setEnabled(subCase, menuLower, selected); Menu.option(subEOL, menuCRLF, T.getEol(text) = RW.EOL_CRLF); Menu.option(subEOL, menuLF, T.getEol(text) = RW.EOL_LF); Menu.option(subEOL, menuCR, T.getEol(text) = RW.EOL_CR); IF menu # NIL THEN Timer.kill; IF Menu.opened(menu) THEN Menu.close(menu) END; Menu.open(menu, x, y); menuActive := TRUE END END ShowMenu; PROCEDURE setScript (VAR script: RW.tFileName); VAR temp: RW.tFileName; BEGIN OpenFile(temp, ShellFilter); IF temp # "" THEN script := temp END END setScript; PROCEDURE receiveIPC; VAR scrollIPC: BOOLEAN; item: List.tItem; BEGIN scrollIPC := FALSE; IF IPC[0] = Timer.ID THEN IF IPC[4] = Timer.n THEN T.toggleCursor; repaint END; IPC[2] := 0 ELSIF IPC[0] = mainTID THEN IF IPC[2] = Scroll.ScrollIPC THEN Scroll.receiveIPC(IPC, scrollIPC) END; IF ~scrollIPC THEN IPC[2] := 0 END ELSE IF ~Menu.isSender(IPC[0]) THEN IPC[2] := 0 ELSE IF IPC[2] < 0 THEN item := List.getItem(mainMenu, (-IPC[2] - mainMenuBtn) MOD mainMenu.count); IF item # NIL THEN ShowMenu(item(Menu.tMainItem).menu) END; IPC[2] := 0 END END END; IF ~scrollIPC THEN CASE IPC[2] OF |0: |menuCut: T.key(text, ORD("X"), FALSE, TRUE) |menuCopy: T.key(text, ORD("C"), FALSE, TRUE) |menuPaste: T.key(text, ORD("V"), FALSE, TRUE) |menuDelete: T.key(text, 46, FALSE, FALSE) |menuSelectAll: T.key(text, ORD("A"), FALSE, TRUE) |menuNew: NewFile |menuOpen: open |menuSave: save(text); repaint |menuSaveAs: saveAs(text); repaint |menuSaveAll: saveAll; repaint |menuClose: closeFile(TRUE, curText) |menuFolder: K.Run("/rd/1/File Managers/Eolite", text.fileName) |menuExit: Close |menuUndo: T.undo(text); repaint |menuRedo: T.redo(text); repaint |menuFind: ShowSearchPanel(FALSE) |menuFindNext: notFound := ~T.findNext(text, BKW.value); menuFindClicked := TRUE |menuFindPrev: notFound := ~T.findNext(text, ~BKW.value); menuFindClicked := TRUE |menuGoto: ShowSearchPanel(TRUE) |menuToggleBookmark: T.toggleLabel(text) |menuNextBookmark: T.gotoLabel(text, TRUE) |menuPrevBookmark: T.gotoLabel(text, FALSE) |menuNumbers: T.toggleNumbers(text) |menuFontSize: IF font = font1 THEN font := font2 ELSE font := font1 END; resize |menuText: T.setLang(text, Languages.langText) |menuC: T.setLang(text, Languages.langC) |menuFasm: T.setLang(text, Languages.langFasm) |menuIni: T.setLang(text, Languages.langIni) |menuJSON: T.setLang(text, Languages.langJSON) |menuLua: T.setLang(text, Languages.langLua) |menuOberon: T.setLang(text, Languages.langOberon) |menuPascal: T.setLang(text, Languages.langPascal) |menuBuild: Script(buildScript) |menuBuildScript: setScript(buildScript) |menuRun: Script(runScript) |menuRunScript: setScript(runScript) |menuDebug: Script(debugScript) |menuDebugScript: setScript(debugScript) |menuUTF8BOM: T.setEnc(text, E.UTF8BOM) |menuUTF8: T.setEnc(text, E.UTF8) |menuCP866: T.setEnc(text, E.CP866) |menuWin1251: T.setEnc(text, E.W1251) |menuLF: T.setEol(text, RW.EOL_LF) |menuCRLF: T.setEol(text, RW.EOL_CRLF) |menuCR: T.setEol(text, RW.EOL_CR) |menuPipet: K.Run("/rd/1/develop/pipet", "") |menuBoard: K.Run("/rd/1/develop/board", "") |menuSysFunc: K.Run("/rd/1/docpack", "f") |menuColors..menuMaxColors: Ini.selectSection(IPC[2] - menuColors) |menuMoveUp: T.upLine(text) |menuMoveDown: T.downLine(text) |menuDuplicate: T.dupLine(text) |menuRemove: T.delLine(text) |menuIncInd: T.Indent(text, TRUE) |menuDecInd: T.Indent(text, FALSE) |menuUpper: T.chCase(text, TRUE) |menuLower: T.chCase(text, FALSE) END; IPC[0] := 0; IPC[1] := 0 END END receiveIPC; PROCEDURE MenuKeyDown (menu: Menu.tMenu; key: INTEGER): BOOLEAN; VAR menuItem: INTEGER; shift, ctrl: BOOLEAN; BEGIN menuItem := -1; K.getKBState(shift, ctrl); IF ctrl THEN CASE key DIV 65536 OF |17: menuItem := menuClose |21: menuItem := menuRedo |30: menuItem := menuSelectAll |32: menuItem := menuDuplicate |33, 35: menuItem := menuFind |34: menuItem := menuGoto |44: menuItem := menuUndo |45: menuItem := menuCut |46: menuItem := menuCopy |47: menuItem := menuPaste |24: menuItem := menuOpen |31: menuItem := menuSave |49: menuItem := menuNew |67: menuItem := menuBuild |83: menuItem := menuRemove |22: menuItem := menuUpper |38: menuItem := menuLower |60: menuItem := menuToggleBookmark |72: menuItem := menuMoveUp |80: menuItem := menuMoveDown ELSE END ELSE IF key DIV 65536 = 83 THEN menuItem := menuDelete ELSIF key DIV 65536 = 67 THEN menuItem := menuRun ELSIF key DIV 65536 = 15 THEN menuItem := menuIncInd ELSIF (key DIV 65536 = 14) & shift THEN menuItem := menuDecInd ELSIF key DIV 65536 = 60 THEN IF shift THEN menuItem := menuPrevBookmark ELSE menuItem := menuNextBookmark END END END; IF menuItem # -1 THEN IF Menu.isEnabled(menu, menuItem) THEN MenuItemClick(menu, menuItem) ELSE menuItem := -1 END END RETURN menuItem # -1 END MenuKeyDown; PROCEDURE CreateContextMenu (): Menu.tMenu; VAR menu: List.tList; BEGIN menu := List.create(NIL); Menu.AddMenuItem(menu, menuUndo, "undo ctrl-Z"); Menu.AddMenuItem(menu, menuRedo, "redo ctrl-Y"); Menu.delimiter(menu); Menu.AddMenuItem(menu, menuCut, "cut ctrl-X"); Menu.AddMenuItem(menu, menuCopy, "copy ctrl-C"); Menu.AddMenuItem(menu, menuPaste, "paste ctrl-V"); Menu.AddMenuItem(menu, menuDelete, "delete"); Menu.delimiter(menu); Menu.AddMenuItem(menu, menuSelectAll, "select all ctrl-A"); RETURN Menu.create(menu, MenuItemClick, MenuKeyDown) END CreateContextMenu; PROCEDURE CreateMenuFile (): Menu.tMenu; VAR menu: List.tList; BEGIN menu := List.create(NIL); Menu.AddMenuItem(menu, menuNew, "new ctrl-N"); Menu.AddMenuItem(menu, menuOpen, "open ctrl-O"); Menu.AddMenuItem(menu, menuSave, "save ctrl-S"); Menu.AddMenuItem(menu, menuSaveAs, "save as"); Menu.AddMenuItem(menu, menuSaveAll, "save all"); Menu.AddMenuItem(menu, menuFolder, "folder"); Menu.delimiter(menu); Menu.AddMenuItem(menu, menuClose, "close ctrl-W"); Menu.delimiter(menu); Menu.AddMenuItem(menu, menuExit, "exit"); RETURN Menu.create(menu, MenuItemClick, MenuKeyDown) END CreateMenuFile; PROCEDURE CreateMenuEdit (): Menu.tMenu; VAR menu: List.tList; BEGIN menu := List.create(NIL); Menu.AddMenuItem(menu, menuUndo, "undo ctrl-Z"); Menu.AddMenuItem(menu, menuRedo, "redo ctrl-Y"); Menu.delimiter(menu); Menu.AddMenuItem(menu, menuCut, "cut ctrl-X"); Menu.AddMenuItem(menu, menuCopy, "copy ctrl-C"); Menu.AddMenuItem(menu, menuPaste, "paste ctrl-V"); Menu.AddMenuItem(menu, menuDelete, "delete"); Menu.delimiter(menu); Menu.AddMenuItem(menu, menuSelectAll, "select all ctrl-A"); Menu.delimiter(menu); Menu.AddMenuItem(menu, menuCurLine, "current line"); Menu.child(menu, subCurLine); Menu.AddMenuItem(menu, menuIndent, "indent"); Menu.child(menu, subIndent); Menu.AddMenuItem(menu, menuCase, "case"); Menu.child(menu, subCase); RETURN Menu.create(menu, MenuItemClick, MenuKeyDown) END CreateMenuEdit; PROCEDURE CreateMenuSearch (): Menu.tMenu; VAR menu: List.tList; BEGIN menu := List.create(NIL); Menu.AddMenuItem(menu, menuFind, "search ctrl-F"); Menu.AddMenuItem(menu, menuFindNext, "find next F3"); Menu.AddMenuItem(menu, menuFindPrev, "find previous shift-F3"); Menu.AddMenuItem(menu, menuGoto, "go to line ctrl-G"); Menu.delimiter(menu); Menu.AddMenuItem(menu, menuBookmark, "bookmark"); Menu.child(menu, subBookmark); RETURN Menu.create(menu, MenuItemClick, MenuKeyDown) END CreateMenuSearch; PROCEDURE CreateMenuEncoding (): Menu.tMenu; VAR menu: List.tList; BEGIN menu := List.create(NIL); Menu.AddMenuItem(menu, menuUTF8BOM, E.names[E.UTF8BOM]); Menu.AddMenuItem(menu, menuUTF8, E.names[E.UTF8]); Menu.AddMenuItem(menu, menuCP866, E.names[E.CP866]); Menu.AddMenuItem(menu, menuWin1251, E.names[E.W1251]); Menu.delimiter(menu); Menu.AddMenuItem(menu, menuEOL, "EOL"); Menu.child(menu, subEOL); RETURN Menu.create(menu, MenuItemClick, MenuKeyDown) END CreateMenuEncoding; PROCEDURE CreateMenuEOL (): Menu.tMenu; VAR menu: List.tList; BEGIN menu := List.create(NIL); Menu.AddMenuItem(menu, menuCRLF, RW.eolNames[RW.EOL_CRLF]); Menu.AddMenuItem(menu, menuLF, RW.eolNames[RW.EOL_LF]); Menu.AddMenuItem(menu, menuCR, RW.eolNames[RW.EOL_CR]); RETURN Menu.create(menu, MenuItemClick, MenuKeyDown) END CreateMenuEOL; PROCEDURE CreateMenuView (): Menu.tMenu; VAR menu: List.tList; colors: Ini.tSection; idx: INTEGER; BEGIN menu := List.create(NIL); Menu.AddMenuItem(menu, menuNumbers, "line numbers"); Menu.AddMenuItem(menu, menuFontSize, "x2"); Menu.delimiter(menu); colors := Ini.sections.first(Ini.tSection); idx := menuColors; WHILE colors # NIL DO Menu.AddMenuItem(menu, idx, colors.name); INC(idx); colors := colors.next(Ini.tSection) END; RETURN Menu.create(menu, MenuItemClick, MenuKeyDown) END CreateMenuView; PROCEDURE CreateMenuLanguage (): Menu.tMenu; VAR menu: List.tList; BEGIN menu := List.create(NIL); Menu.AddMenuItem(menu, menuC, "C"); Menu.AddMenuItem(menu, menuFasm, "Fasm"); Menu.AddMenuItem(menu, menuIni, "Ini"); Menu.AddMenuItem(menu, menuJSON, "JSON"); Menu.AddMenuItem(menu, menuLua, "Lua"); Menu.AddMenuItem(menu, menuOberon, "Oberon"); Menu.AddMenuItem(menu, menuPascal, "Pascal"); Menu.delimiter(menu); Menu.AddMenuItem(menu, menuText, "Text"); RETURN Menu.create(menu, MenuItemClick, MenuKeyDown) END CreateMenuLanguage; PROCEDURE CreateMenuProgram (): Menu.tMenu; VAR menu: List.tList; BEGIN menu := List.create(NIL); Menu.AddMenuItem(menu, menuBuild, "build ctrl-F9"); Menu.AddMenuItem(menu, menuBuildScript, "script"); Menu.delimiter(menu); Menu.AddMenuItem(menu, menuRun, "run F9"); Menu.AddMenuItem(menu, menuRunScript, "script"); Menu.delimiter(menu); Menu.AddMenuItem(menu, menuDebug, "debug"); Menu.AddMenuItem(menu, menuDebugScript, "script"); RETURN Menu.create(menu, MenuItemClick, MenuKeyDown) END CreateMenuProgram; PROCEDURE CreateMenuTools (): Menu.tMenu; VAR menu: List.tList; BEGIN menu := List.create(NIL); Menu.AddMenuItem(menu, menuPipet, "pipet"); Menu.AddMenuItem(menu, menuBoard, "board"); Menu.AddMenuItem(menu, menuSysFunc, "system functions"); RETURN Menu.create(menu, MenuItemClick, MenuKeyDown) END CreateMenuTools; PROCEDURE CreateMenuCurLine(): Menu.tMenu; VAR menu: List.tList; BEGIN menu := List.create(NIL); Menu.AddMenuItem(menu, menuMoveUp, "move up ctrl-Up"); Menu.AddMenuItem(menu, menuMoveDown, "move down ctrl-Down"); Menu.AddMenuItem(menu, menuDuplicate, "duplicate ctrl-D"); Menu.AddMenuItem(menu, menuRemove, "remove ctrl-Del"); RETURN Menu.create(menu, MenuItemClick, MenuKeyDown) END CreateMenuCurLine; PROCEDURE CreateMenuIndent(): Menu.tMenu; VAR menu: List.tList; BEGIN menu := List.create(NIL); Menu.AddMenuItem(menu, menuIncInd, "increase Tab"); Menu.AddMenuItem(menu, menuDecInd, "decrease shift-Bksp"); RETURN Menu.create(menu, MenuItemClick, MenuKeyDown) END CreateMenuIndent; PROCEDURE CreateMenuCase(): Menu.tMenu; VAR menu: List.tList; BEGIN menu := List.create(NIL); Menu.AddMenuItem(menu, menuUpper, "UPPER ctrl-U"); Menu.AddMenuItem(menu, menuLower, "lower ctrl-L"); RETURN Menu.create(menu, MenuItemClick, MenuKeyDown) END CreateMenuCase; PROCEDURE CreateMenuBookmark(): Menu.tMenu; VAR menu: List.tList; BEGIN menu := List.create(NIL); Menu.AddMenuItem(menu, menuToggleBookmark, "toggle ctrl-F2"); Menu.AddMenuItem(menu, menuNextBookmark, "next F2"); Menu.AddMenuItem(menu, menuPrevBookmark, "previous shift-F2"); RETURN Menu.create(menu, MenuItemClick, MenuKeyDown) END CreateMenuBookmark; PROCEDURE HideSearch; BEGIN SetFocus(FindEdit, FALSE); searchOpened := FALSE; LEFT := searchLeft; resize; draw_window END HideSearch; PROCEDURE KeyDown (key: INTEGER); VAR keyCode: INTEGER; shift, ctrl: BOOLEAN; BEGIN K.getKBState(shift, ctrl); keyCode := key DIV 65536; IF confirm THEN IF keyCode = 28 THEN (* Enter *) save(text); IF ~text.modified THEN closeFile(FALSE, curText) END END; key := -1 ELSE IF keyCode = 61 THEN (* F3 *) key := -1; IF search & (searchText # "") THEN IF shift THEN notFound := ~T.findNext(text, ~BKW.value) ELSE notFound := ~T.findNext(text, BKW.value) END END ELSIF keyCode = 60 THEN (* F2 *) key := -1; IF ctrl THEN T.toggleLabel(text) ELSE T.gotoLabel(text, ~shift) END ELSIF keyCode = 67 THEN (* F9 *) key := -1; IF ctrl THEN Script(buildScript) ELSE Script(runScript) END ELSIF keyCode = 68 THEN (* F10 *) IF shift THEN ShowMenu(context) ELSE ShowMenu(menuFile) END; key := -1 ELSIF keyCode = 1 THEN (* Esc *) IF search THEN IF shift THEN HideSearch ELSE Search END END; key := -1 ELSIF (keyCode = 55) & (key DIV 256 MOD 256 = 52) THEN (* PrtScn *) key := -1 ELSIF (keyCode = 14) & shift THEN (* shift+Backspace *) key := -1; T.input(text, -8) ELSIF (keyCode = 15) & ctrl THEN (* ctrl+Tab *) key := -1; SwitchTab((curText + 1) MOD textsCount) ELSIF ((keyCode = 33) OR (keyCode = 35)) & ctrl THEN (* ctrl+F, ctrl+H*) key := -1; ShowSearchPanel(FALSE) ELSIF (keyCode = 34) & ctrl THEN (* ctrl+G *) key := -1; ShowSearchPanel(TRUE) ELSIF (keyCode = 18) & ctrl THEN (* ctrl+E *) key := -1; T.selectWord(text) ELSE IF EditBox_Focus(FindEdit) THEN IF keyCode = 15 THEN (* Tab *) SetFocus(ReplaceEdit, TRUE) ELSE EB.key(FindEdit, key); EditBox_GetValue(FindEdit, new_searchText); IF new_searchText # searchText THEN searchText := new_searchText; notFound := ~T.search(text, searchText, cs, whole) END END ELSIF EditBox_Focus(ReplaceEdit) THEN IF keyCode = 15 THEN (* Tab *) SetFocus(GotoEdit, TRUE) ELSE EB.key(ReplaceEdit, key); EditBox_GetValue(ReplaceEdit, replaceText) END ELSIF EditBox_Focus(GotoEdit) THEN IF keyCode = 15 THEN (* Tab *) SetFocus(FindEdit, TRUE) ELSE IF (key DIV 256) MOD 256 = 13 THEN goto ELSE EB.key(GotoEdit, key) END END ELSE CASE keyCode OF |73: key := 33 |81: key := 34 |71: key := 36 |79: key := 35 |72: key := 38 |80: key := 40 |75: key := 37 |77: key := 39 |82, 91, 219, 92, 220: key := -1 (* insert, windows *) |93: ShowMenu(context); key := -1 |83: key := 46 |59, 62..66, 87, 88: key := -1 (* F1, F4..F8, F11, F12 *) ELSE IF ctrl THEN CASE keyCode OF |17: closeFile(TRUE, curText); key := -2 |21: T.redo(text); key := -1 |22: key := ORD("U") |24: key := -1; open |30: key := ORD("A") |31: key := -1; save(text) |32: key := ORD("D") |38: key := ORD("L") |44: T.undo(text); key := -1 |45: key := ORD("X") |46: key := ORD("C") |47: key := ORD("V") |49: key := -1; NewFile ELSE key := -1 END ELSE T.input(text, E.cp866[key DIV 256 MOD 256]); key := -1 END END; IF key >= 0 THEN T.key(text, key, shift, ctrl) END END END END; IF key # -2 THEN repaint END END KeyDown; PROCEDURE BtnClick; VAR btn: INTEGER; middle, exit: BOOLEAN; menu: Menu.tMenu; BEGIN btn := K.ButtonCode(middle); IF U.between(Tabs.btnID, btn, Tabs.btnID + maxTexts - 1) THEN DEC(btn, Tabs.btnID); IF middle THEN IF texts[btn].modified THEN SwitchTab(btn) END; closeFile(TRUE, btn) ELSE SwitchTab(btn) END; btn := 0 ELSE IF middle THEN btn := 0 END END; IF btn # 0 THEN menu := Menu.ClickMain(mainMenu, btn); IF menu # NIL THEN ShowMenu(menu); btn := 0 END END; CASE btn OF |Tabs.btnID - 1: Tabs.scroll(tabs, -1); switch := TRUE; repaint |Tabs.btnID - 2: Tabs.scroll(tabs, +1); switch := TRUE; repaint |0: |btnNo: exit := closing; closeFile(FALSE, curText); repaint; IF exit THEN Close END |btnYes: exit := closing; save(text); IF ~text.modified THEN closeFile(FALSE, curText) END; repaint; IF exit THEN Close END |btnClose: Close |btnNew: NewFile; repaint |btnOpen: open |btnSave: save(text); repaint |btnSearch: ShowSearchPanel(FALSE); repaint |btnCloseSearch: Search |btnHideSearch: HideSearch |btnUndo: T.undo(text); repaint |btnRedo: T.redo(text); repaint |btnUpper: T.chCase(text, TRUE); repaint |btnLower: T.chCase(text, FALSE); repaint |btnBuild: Script(buildScript) |btnRun: Script(runScript) |btnFindNext: IF searchText # "" THEN notFound := ~T.findNext(text, BKW.value); repaint END |btnReplace: T.replace(text, replaceText, LENGTH(searchText)); repaint |btnReplaceAll: notFound := ~T.search(text, searchText, cs, whole); IF ~notFound THEN replaced := T.replaceAll(text, replaceText, LENGTH(searchText)); END; repaint |btnGoto: goto; repaint END END BtnClick; PROCEDURE MouseEvent (VAR resized: BOOLEAN; VAR firstClickX, firstClickY, time: INTEGER); CONST DELAY = 10; VAR msState: SET; scroll, x, y, scrollX, scrollY: INTEGER; pos1, pos2: T.tPoint; PROCEDURE EditBox (VAR eb: EB.tEditBox); VAR focus: BOOLEAN; BEGIN focus := EditBox_Focus(eb); EB.mouse(eb); IF focus # EditBox_Focus(eb) THEN SetFocus(eb, TRUE); repaint END END EditBox; BEGIN CloseMenu; IF ~resized THEN msState := K.MouseState(); IF ~(0 IN msState) OR (16 IN msState) THEN leftButton := FALSE END; scroll := K.Scroll(); IF scroll # 0 THEN T.scroll(text, 0, scroll*3); repaint END; IF leftButton THEN IF K.GetTickCount() - time >= DELAY THEN T.getPos(text, pos1.Y, pos1.X); mouse(x, y); T.mouse(text, x, y); T.getPos(text, pos2.Y, pos2.X); IF (pos1.X # pos2.X) OR (pos1.Y # pos2.Y) THEN repaint END END END; Scroll.mouse(hScroll); Scroll.mouse(vScroll); T.getScroll(text, scrollX, scrollY); IF (hScroll.value # scrollX) OR (vScroll.value # scrollY) THEN T.scroll(text, hScroll.value - scrollX, vScroll.value - scrollY); repaint END; IF (8 IN msState) & ~(24 IN msState) THEN mouse(firstClickX, firstClickY); time := click(firstClickX, firstClickY) END; IF 9 IN msState THEN ShowMenu(context) END; IF 24 IN msState THEN mouse(x, y); IF U.between(-4, x - firstClickX, 4) & U.between(-4, y - firstClickY, 4) THEN IF U.between(0, x, canvas.width - 1) & U.between(0, y, canvas.height - 1) THEN leftButton := FALSE; T.selectWord(text); repaint END ELSE firstClickX := x; firstClickY := y; time := click(firstClickX, firstClickY) END END END; IF search & searchOpened THEN CheckBox.mouse(BKW); CheckBox.mouse(CS); CheckBox.mouse(WH); EditBox(FindEdit); EditBox(ReplaceEdit); EditBox(GotoEdit); IF (CS.value # cs) OR (WH.value # whole) THEN cs := CS.value; whole := WH.value; notFound := ~T.search(text, searchText, cs, whole); repaint END END; resized := FALSE END MouseEvent; PROCEDURE Redraw (VAR resized: BOOLEAN; VAR width, height, cliWidth, cliHeight: INTEGER); VAR i: INTEGER; BEGIN K.GetSystemColors; Icons.get(icons, grayIcons); FOR i := 0 TO 1 DO IF ~K.RolledUp() THEN K.ClientSize(width, height); IF (width # cliWidth) OR (height # cliHeight) THEN cliWidth := width; cliHeight := height; resize; resized := TRUE END; K.SetEventsMask({0, 1, 2, 5, 6, 31}) ELSE SetCaption(text.fileName); K.SetEventsMask({0, 30, 31}) END; draw_window END END Redraw; PROCEDURE ScrollChange; BEGIN Scroll.change(hScroll); Scroll.change(vScroll); T.scroll(text, ORD(hScroll.Inc) - ORD(hScroll.Dec), ORD(vScroll.Inc) - ORD(vScroll.Dec)); IF menuActive THEN draw_window; menuActive := FALSE ELSE repaint END END ScrollChange; PROCEDURE main; VAR err: INTEGER; fileName, filePath: RW.tFileName; width, height, cliWidth, cliHeight: INTEGER; resized: BOOLEAN; firstClickX, firstClickY, time: INTEGER; BEGIN K.GetSystemColors; Icons.get(icons, grayIcons); modified := FALSE; switch := FALSE; closing := FALSE; textsCount := 0; curText := 0; mainTID := K.ThreadID(); K.SetIPC(IPC); U.ptr2str(K.GetName(), AppPath); Ini.load(AppPath); leftButton := FALSE; resized := FALSE; K.ScreenSize(winWidth, winHeight); winWidth := (winWidth*80) DIV 100 - (128 + 30); winHeight := winHeight - (128 + 30); winWidth := MAX(winWidth, minWinWidth); winHeight := MAX(winHeight, minWinHeight); cliWidth := winWidth; cliHeight := winHeight; LEFT := searchLeft; canvas := G.CreateCanvas(winWidth - (LEFT + RIGHT + 11), winHeight - (TOP + BOTTOM + 5) - K.SkinHeight()); tabs := Tabs.create(); Tabs.setArea(tabs, LEFT, TOP - Tabs.tabHeight, canvas.width, Tabs.tabHeight); font1 := G.CreateFont(1, "", {}); font2 := G.CreateFont(2, "", {}); font := font1; G.SetFont(canvas, font); T.init(resetTimer); T.setCanvas(canvas); U.ptr2str(K.GetCommandLine(), fileName); context := CreateContextMenu(); menuFile := CreateMenuFile(); subCurLine := CreateMenuCurLine(); subIndent := CreateMenuIndent(); subCase := CreateMenuCase(); menuEdit := CreateMenuEdit(); subCurLine.parent := menuEdit; subIndent.parent := menuEdit; subCase.parent := menuEdit; subBookmark := CreateMenuBookmark(); menuSearch := CreateMenuSearch(); subBookmark.parent := menuSearch; subEOL := CreateMenuEOL(); menuEncoding := CreateMenuEncoding(); subEOL.parent := menuEncoding; menuView := CreateMenuView(); menuLanguage := CreateMenuLanguage(); menuProgram := CreateMenuProgram(); menuTools := CreateMenuTools(); mainMenu := Menu.CreateMain(mainMenuBtn); Menu.AddMainItem(mainMenu, "file", menuFile); Menu.AddMainItem(mainMenu, "edit", menuEdit); Menu.AddMainItem(mainMenu, "search", menuSearch); Menu.AddMainItem(mainMenu, "encoding", menuEncoding); Menu.AddMainItem(mainMenu, "view", menuView); Menu.AddMainItem(mainMenu, "language", menuLanguage); Menu.AddMainItem(mainMenu, "program", menuProgram); Menu.AddMainItem(mainMenu, "tools", menuTools); Ini.getSettings(buildScript, runScript, debugScript); IF fileName = "" THEN text := T.New(); filePath := "/rd/1" ELSE text := T.open(fileName, err); IF text = NIL THEN error("error opening file"); K.Exit ELSE U.getPath(fileName, filePath) END END; OD := OpenDlg.Create(draw_window, OpenDlg.topen, filePath, ""); insert(0, text); Scroll.init(ScrollChange); Scroll.create(FALSE, canvas.width + 1, scrollWidth, scrollWidth, scrollWidth*3 DIV 2, hScroll); Scroll.create(TRUE, scrollWidth, canvas.height + 1, scrollWidth, scrollWidth*3 DIV 2, vScroll); T.resize(canvas.width, canvas.height); T.SetPos(text, 0, 0); confirm := FALSE; notFound := FALSE; menuFindClicked := FALSE; menuActive := FALSE; search := FALSE; searchOpened := FALSE; createSearchForm; new_searchText := ""; searchText := ""; cs := FALSE; whole := FALSE; replaced := 0; K.SetEventsMask({0, 1, 2, 5, 6, 31}); Menu.init(resetTimer); draw_window; Timer.create(mainTID); WHILE TRUE DO CASE K.WaitForEvent() OF |1: Redraw(resized, width, height, cliWidth, cliHeight) |2: KeyDown(K.GetKey()) |3: BtnClick |6: MouseEvent(resized, firstClickX, firstClickY, time) |7: receiveIPC END END END main; BEGIN main END CEdit.