Subversion Repositories Kolibri OS

Rev

Rev 9073 | Rev 9175 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. (*
  2.     Copyright 2021 Anton Krotov
  3.  
  4.     This file is part of CEdit.
  5.  
  6.     CEdit is free software: you can redistribute it and/or modify
  7.     it under the terms of the GNU General Public License as published by
  8.     the Free Software Foundation, either version 3 of the License, or
  9.     (at your option) any later version.
  10.  
  11.     CEdit is distributed in the hope that it will be useful,
  12.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.     GNU General Public License for more details.
  15.  
  16.     You should have received a copy of the GNU General Public License
  17.     along with CEdit. If not, see <http://www.gnu.org/licenses/>.
  18. *)
  19.  
  20. MODULE CEdit;
  21.  
  22. IMPORT
  23.     OpenDlg, K := KolibriOS,
  24.     U := Utils, Lines, Menu, List,
  25.     G := Graph, T := Text, E := Encodings,
  26.     CB := Clipboard, Languages,
  27.     ChangeLog, Scroll,
  28.     RW, Ini, box_lib, Icons, Tabs, Timer;
  29.  
  30. CONST
  31.     header = "CEdit (02-sep-2021)";
  32.  
  33.     ShellFilter = "";
  34.     EditFilter = "SH|ASM|TXT|INC|OB07|C|CPP|H|PAS|PP|LUA|INI|JSON";
  35.  
  36.     fontWidth = K.fontWidth;
  37.     fontHeight = K.fontHeight;
  38.     scrollWidth = 22;
  39.  
  40.     btnClose = 1;
  41.     btnNew = 20;
  42.     btnOpen = 21;
  43.     btnSave = 22;
  44.     btnSearch = 23;
  45.     btnUndo = 24;
  46.     btnRedo = 25;
  47.     btnUpper = 26;
  48.     btnLower = 27;
  49.     btnBuild = 28;
  50.     btnRun = 29;
  51.  
  52.     btnYes = 40;
  53.     btnNo = 41;
  54.     btnFindNext = 60;
  55.     btnReplace = 61;
  56.     btnReplaceAll = 62;
  57.     btnGoto = 63;
  58.     btnCloseFind = 64;
  59.     btnHideFind = 65;
  60.  
  61.     btnFile = 70;
  62.     btnEdit = 71;
  63.     btnMenuSearch = 72;
  64.     btnEncoding = 73;
  65.     btnView = 74;
  66.     btnSyntax = 75;
  67.     btnProgram = 76;
  68.     btnTools = 77;
  69.  
  70.     MainMenuHeight = fontHeight + 7;
  71.  
  72.     btnHeight = 25;
  73.     btnWidth = 75;
  74.     btnTop = MainMenuHeight + 3;
  75.     toolBtnSize = 24;
  76.     toolbarDelim = 7;
  77.     iconPad = (toolBtnSize - Icons.SIZE) DIV 2;
  78.  
  79.     TOP = btnTop + toolBtnSize + 10 + Tabs.tabHeight;
  80.     RIGHT = scrollWidth - 2;
  81.     BOTTOM = scrollWidth + 18;
  82.  
  83.     minWinWidth = 635; minWinHeight = 538;
  84.  
  85.     SEARCH_PADDING = 10;
  86.     searchLeft = 0;
  87.     EditBox_Width = 180;
  88.     EDITBOX_MAXCHARS = 500;
  89.  
  90.     menuFileX = searchLeft;
  91.     menuEditX = menuFileX + 4*fontWidth + 2 + 7;
  92.     menuSearchX = menuEditX + 4*fontWidth + 2 + 7;
  93.     menuEncodingX = menuSearchX + 6*fontWidth + 2 + 7;
  94.     menuViewX = menuEncodingX + 8*fontWidth + 2 + 7;
  95.     menuSyntaxX = menuViewX + 4*fontWidth + 2 + 7;
  96.     menuProgramX = menuSyntaxX + 6*fontWidth + 2 + 7;
  97.     menuToolsX = menuProgramX + 7*fontWidth + 2 + 7;
  98.  
  99.     menuCut = 1;
  100.     menuCopy = 2;
  101.     menuPaste = 3;
  102.     menuDelete = 4;
  103.     menuSelectAll = 5;
  104.  
  105.     menuUndo = 6;
  106.     menuRedo = 7;
  107.  
  108.     menuCurLine = 100;
  109.     menuIndent = 110;
  110.     menuCase = 120;
  111.  
  112.     menuNew = 10;
  113.     menuOpen = 11;
  114.     menuSave = 12;
  115.     menuSaveAs = 13;
  116.     menuSaveAll = 14;
  117.     menuFolder = 15;
  118.     menuClose = 16;
  119.     menuExit = 17;
  120.  
  121.     menuNumbers = 20;
  122.     menuFontSize = 21;
  123.     menuColors = 1000;
  124.     menuMaxColors = menuColors + Ini.MAX_SECTIONS - 1;
  125.  
  126.     menuNone = 30;
  127.     menuC = 31;
  128.     menuFasm = 32;
  129.     menuIni = 33;
  130.     menuJSON = 34;
  131.     menuLua = 35;
  132.     menuOberon = 36;
  133.     menuPascal = 37;
  134.  
  135.     menuBuild = 50;
  136.     menuBuildScript = 51;
  137.     menuRun = 52;
  138.     menuRunScript = 53;
  139.     menuDebug = 54;
  140.     menuDebugScript = 55;
  141.  
  142.     menuUTF8BOM = 60;
  143.     menuUTF8 = 61;
  144.     menuCP866 = 62;
  145.     menuWin1251 = 63;
  146.  
  147.     menuPipet = 70;
  148.     menuBoard = 71;
  149.     menuSysFunc = 72;
  150.  
  151.     menuFind = 80;
  152.     menuFindNext = 81;
  153.     menuFindPrev = 82;
  154.     menuGoto = 83;
  155.     menuBookmark = 130;
  156.  
  157.     menuMoveUp = 101;
  158.     menuMoveDown = 102;
  159.     menuDuplicate = 103;
  160.     menuRemove = 104;
  161.  
  162.     menuIncInd = 111;
  163.     menuDecInd = 112;
  164.  
  165.     menuUpper = 121;
  166.     menuLower = 122;
  167.  
  168.     menuToggleBookmark = 131;
  169.     menuNextBookmark = 132;
  170.     menuPrevBookmark = 133;
  171.  
  172.     maxTexts = 32;
  173.     scrollDelay = 40;
  174.  
  175.  
  176. VAR
  177.     canvas: G.tCanvas;
  178.     font, font1, font2: G.tFont;
  179.  
  180.     tabs: Tabs.tTabs;
  181.     text: T.tText;
  182.     texts: ARRAY maxTexts OF T.tText;
  183.     textsCount, curText: INTEGER;
  184.  
  185.     winWidth, winHeight: INTEGER;
  186.     AppPath, runScript, buildScript, debugScript: RW.tFileName;
  187.     OD: OpenDlg.Dialog;
  188.     confirm, notFound, search, searchOpened, modified: BOOLEAN;
  189.  
  190.     switch, closing: BOOLEAN;
  191.     leftButton: BOOLEAN;
  192.     hScroll, vScroll: Scroll.tScroll;
  193.     LEFT: INTEGER;
  194.  
  195.     FindEdit, ReplaceEdit, GotoEdit: box_lib.edit_box;
  196.     CS, WH, BKW: box_lib.checkbox;
  197.  
  198.     new_searchText, searchText, replaceText, gotoText: T.tString;
  199.     cs, whole: BOOLEAN;
  200.  
  201.     replaced: INTEGER;
  202.  
  203.     mainTID, delay: INTEGER;
  204.  
  205.     context, menuFile, menuEdit, menuSearch, menuEncoding,
  206.     menuView, menuSyntax, menuProgram, menuTools,
  207.     subCurLine, subIndent, subCase, subBookmark: Menu.tMenu;
  208.  
  209.     icons: INTEGER;
  210.     grayIcons: INTEGER;
  211.  
  212.     IPC: ARRAY 64 OF INTEGER;
  213.  
  214.  
  215. PROCEDURE WritePos (y: INTEGER);
  216. VAR
  217.     s1, s2: ARRAY 32 OF WCHAR;
  218.     line, col: INTEGER;
  219. BEGIN
  220.     T.getPos(text, col, line);
  221.     U.int2str(line, s1);
  222.     U.int2str(col, s2);
  223.     U.append(s1, ": ");
  224.     U.append(s1, s2);
  225.     K.DrawText(LEFT, y, K.textColor, s1)
  226. END WritePos;
  227.  
  228.  
  229. PROCEDURE EditBox_Focus (edit: box_lib.edit_box): BOOLEAN;
  230. VAR
  231.         res: BOOLEAN;
  232. BEGIN
  233.         res := FALSE;
  234.         IF edit # NIL THEN
  235.             res := 1 IN BITS(edit.flags)
  236.         END
  237.         RETURN res
  238. END EditBox_Focus;
  239.  
  240.  
  241. PROCEDURE resetTimer;
  242. BEGIN
  243.         IF EditBox_Focus(FindEdit) OR EditBox_Focus(ReplaceEdit) OR EditBox_Focus(GotoEdit) THEN
  244.                 T.hideCursor;
  245.                 Timer.stop
  246.         ELSE
  247.                 T.showCursor;
  248.                 Timer.reset
  249.         END
  250. END resetTimer;
  251.  
  252.  
  253. PROCEDURE EditBox_SetFocus (edit: box_lib.edit_box; value: BOOLEAN);
  254. BEGIN
  255.     IF value THEN
  256.         edit.flags := ORD(BITS(edit.flags) + {1})
  257.     ELSE
  258.         edit.flags := ORD(BITS(edit.flags) - {1})
  259.     END;
  260.     IF search & searchOpened THEN
  261.         box_lib.edit_box_draw(edit)
  262.     END
  263. END EditBox_SetFocus;
  264.  
  265.  
  266. PROCEDURE SetFocus (edit: box_lib.edit_box; value: BOOLEAN);
  267. BEGIN
  268.     EditBox_SetFocus(FindEdit, FALSE);
  269.     EditBox_SetFocus(ReplaceEdit, FALSE);
  270.     EditBox_SetFocus(GotoEdit, FALSE);
  271.     EditBox_SetFocus(edit, value);
  272.         resetTimer
  273. END SetFocus;
  274.  
  275.  
  276. PROCEDURE Rect (left, top, right, bottom, color: INTEGER);
  277. BEGIN
  278.     K.DrawLine(left, top, right, top, color);
  279.     K.DrawLine(left, bottom, right, bottom, color);
  280.     K.DrawLine(left, top, left, bottom, color);
  281.     K.DrawLine(right, top, right, bottom, color);
  282. END Rect;
  283.  
  284.  
  285. PROCEDURE Message (s: ARRAY OF WCHAR);
  286. CONST
  287.     minWidth = 30;
  288.     height = 40;
  289.     borderColor = 808080H;
  290. VAR
  291.     top, left, right, bottom, x, y, width: INTEGER;
  292. BEGIN
  293.         Timer.stop;
  294.     width := minWidth + LENGTH(s)*fontWidth;
  295.     left := (canvas.width - width) DIV 2 + LEFT;
  296.     top := (canvas.height - height) DIV 2 + TOP;
  297.     bottom := top + height - 1;
  298.     right := left + width - 1;
  299.     x := minWidth DIV 2 + left;
  300.     y := (height - fontHeight) DIV 2 + top;
  301.     K.DrawRect(left, top, width, height, K.winColor);
  302.     Rect(left, top, right, bottom, borderColor);
  303.     K.DrawText(x, y, K.textColor, s);
  304. END Message;
  305.  
  306.  
  307. PROCEDURE NotFound;
  308. BEGIN
  309.     IF notFound THEN
  310.         Message("not found");
  311.         notFound := FALSE;
  312.         SetFocus(FindEdit, TRUE)
  313.     END
  314. END NotFound;
  315.  
  316.  
  317. PROCEDURE Replaced;
  318. VAR
  319.     s, s1: ARRAY 32 OF WCHAR;
  320. BEGIN
  321.     IF replaced # 0 THEN
  322.         s := "replaced: ";
  323.         U.int2str(replaced, s1);
  324.         U.append(s, s1);
  325.         Message(s);
  326.         replaced := 0;
  327.         SetFocus(FindEdit, TRUE)
  328.     END
  329. END Replaced;
  330.  
  331.  
  332. PROCEDURE toolbarIcons;
  333. VAR
  334.     x, color: INTEGER;
  335. BEGIN
  336.     x := searchLeft + (toolBtnSize + 5)*2;
  337.     IF text.modified THEN
  338.         Icons.draw(icons, 5, x + iconPad, btnTop + iconPad)
  339.     ELSE
  340.         Icons.draw(grayIcons, 5, x + iconPad, btnTop + iconPad)
  341.     END;
  342.  
  343.     IF text.edition # NIL THEN
  344.         x := searchLeft + (toolBtnSize + 5)*4 + toolbarDelim*2;
  345.         IF ChangeLog.isFirstGuard(text.edition) THEN
  346.             Icons.draw(grayIcons, 37, x + iconPad, btnTop + iconPad)
  347.         ELSE
  348.             Icons.draw(icons, 37, x + iconPad, btnTop + iconPad)
  349.         END;
  350.  
  351.         x := searchLeft + (toolBtnSize + 5)*5 + toolbarDelim*2;
  352.         IF ChangeLog.isLastGuard(text.edition) THEN
  353.             Icons.draw(grayIcons, 36, x + iconPad, btnTop + iconPad)
  354.         ELSE
  355.             Icons.draw(icons, 36, x + iconPad, btnTop + iconPad)
  356.         END
  357.     END;
  358.  
  359.     IF T.selected(text) THEN
  360.         color := K.caseColor
  361.     ELSE
  362.         color := K.disCaseColor
  363.     END;
  364.  
  365.     x := searchLeft + (toolBtnSize + 5)*6 + toolbarDelim*3;
  366.     K.DrawRect(x, btnTop, toolBtnSize, toolBtnSize, K.toolbarColor);
  367.     K.DrawText69(x + (toolBtnSize - 12) DIV 2, btnTop + (toolBtnSize - 9) DIV 2 + 2, color, "AB");
  368.     INC(x, toolBtnSize + 5);
  369.     K.DrawRect(x, btnTop, toolBtnSize, toolBtnSize, K.toolbarColor);
  370.     K.DrawText69(x + (toolBtnSize - 12) DIV 2, btnTop + (toolBtnSize - 9) DIV 2 + 2, color, "ab");
  371.  
  372.     x := searchLeft + (toolBtnSize + 5)*8 + toolbarDelim*4;
  373.     IF buildScript # "" THEN
  374.         Icons.draw(icons, 54, x + iconPad, btnTop + iconPad)
  375.     ELSE
  376.         Icons.draw(grayIcons, 54, x + iconPad, btnTop + iconPad)
  377.     END;
  378.     INC(x, toolBtnSize + 5);
  379.     IF runScript # "" THEN
  380.         Icons.draw(icons, 53, x + iconPad, btnTop + iconPad)
  381.     ELSE
  382.         Icons.draw(grayIcons, 53, x + iconPad, btnTop + iconPad)
  383.     END
  384. END toolbarIcons;
  385.  
  386.  
  387. PROCEDURE WriteModified (x, y: INTEGER);
  388. BEGIN
  389.     modified := text.modified;
  390.     K.DrawRect(x, TOP + canvas.height + scrollWidth - 1, 8*fontWidth, BOTTOM - scrollWidth + 1, K.winColor);
  391.     IF modified THEN
  392.         K.DrawText866(x, y, K.textColor, "modified")
  393.     END
  394. END WriteModified;
  395.  
  396.  
  397. PROCEDURE DrawState (text: T.tText; width, height: INTEGER);
  398. VAR
  399.     y: INTEGER;
  400. BEGIN
  401.     y := (btnHeight - fontHeight) DIV 2 + btnTop;
  402.     K.DrawRect(width - 16*fontWidth, y, 16*fontWidth, fontHeight, K.winColor);
  403.     K.DrawText(width - LENGTH(E.names[text.enc])*fontWidth, y, K.textColor, E.names[text.enc]);
  404.     y := height - (BOTTOM - scrollWidth) + (BOTTOM - scrollWidth - 16) DIV 2;
  405.     K.DrawRect(LEFT + 16*fontWidth, TOP + canvas.height + scrollWidth - 1, width - LEFT - 24*fontWidth, BOTTOM - scrollWidth + 1, K.winColor);
  406.     K.DrawText866(LEFT + 16*fontWidth, y, K.textColor, text.fileName);
  407.     WriteModified(width - 8*fontWidth, y)
  408. END DrawState;
  409.  
  410.  
  411. PROCEDURE DrawScroll (VAR scroll: Scroll.tScroll; left, top, value, maxVal: INTEGER);
  412. BEGIN
  413.         scroll.maxVal := maxVal;
  414.     scroll.left := left;
  415.     scroll.top := top;
  416.     Scroll.setValue(scroll, value);
  417.     Scroll.paint(scroll)
  418. END DrawScroll;
  419.  
  420.  
  421. PROCEDURE repaint;
  422. VAR
  423.     width, height, scrollX, scrollY, y: INTEGER;
  424. BEGIN
  425.     IF text # NIL THEN
  426.         IF confirm THEN
  427.             K.DeleteButton(btnYes);
  428.             K.DeleteButton(btnNo);
  429.             confirm := FALSE;
  430.             resetTimer;
  431.             closing := FALSE
  432.         END;
  433.         IF ~search OR (searchText = "") THEN
  434.             T.wordSel(text)
  435.         END;
  436.         K.ClientSize(width, height);
  437.         IF switch THEN
  438.             DrawState(text, width, height);
  439.             Tabs.draw(tabs);
  440.             IF search & T.search(text, searchText, cs, whole) THEN END;
  441.             switch := FALSE
  442.         END;
  443.         T.draw(text);
  444.         y := height - (BOTTOM - scrollWidth) + (BOTTOM - scrollWidth - 16) DIV 2;
  445.         K.DrawRect(LEFT, TOP + canvas.height + scrollWidth - 1, 16*fontWidth, BOTTOM - scrollWidth + 1, K.winColor);
  446.         WritePos(y);
  447.  
  448.         IF modified # text.modified THEN
  449.             WriteModified(width - 8*fontWidth, y)
  450.         END;
  451.  
  452.         T.getScroll(text, scrollX, scrollY);
  453.         DrawScroll(vScroll, LEFT + canvas.width - 1, TOP - 1, scrollY, text.count - 1);
  454.         DrawScroll(hScroll, LEFT, TOP + canvas.height - 1, scrollX, text.maxLength);
  455.  
  456.         G.DrawCanvas(canvas, LEFT, TOP);
  457.         NotFound;
  458.         Replaced;
  459.         toolbarIcons
  460.     END
  461. END repaint;
  462.  
  463.  
  464. PROCEDURE resize;
  465. VAR
  466.     cliWidth, cliHeight: INTEGER;
  467. BEGIN
  468.     K.WinSize(winWidth, winHeight);
  469.     IF winWidth < minWinWidth THEN
  470.         winWidth := minWinWidth
  471.     END;
  472.     IF winHeight < minWinHeight THEN
  473.         winHeight := minWinHeight
  474.     END;
  475.     K.SetWinSize(winWidth, winHeight);
  476.     K.WinSize(winWidth, winHeight);
  477.     K.ClientSize(cliWidth, cliHeight);
  478.     G.destroy(canvas);
  479.     canvas := G.CreateCanvas(cliWidth - (LEFT + RIGHT + 1), cliHeight - (TOP + BOTTOM));
  480.     Tabs.setArea(tabs, LEFT, TOP - Tabs.tabHeight, cliWidth - (LEFT + RIGHT + 1), Tabs.tabHeight);
  481.     G.SetFont(canvas, font);
  482.     T.setCanvas(canvas);
  483.     T.resize(canvas.width, canvas.height);
  484.     Scroll.resize(vScroll, vScroll.width, canvas.height + 1);
  485.     Scroll.resize(hScroll, canvas.width, hScroll.height);
  486. END resize;
  487.  
  488.  
  489. PROCEDURE SearchPanel (left, top: INTEGER);
  490. VAR
  491.     y, right, bottom, color: INTEGER;
  492. BEGIN
  493.     DEC(top, Tabs.tabHeight);
  494.     right := left + EditBox_Width + SEARCH_PADDING*2;
  495.     bottom := top + 395 + btnHeight + SEARCH_PADDING;
  496.     color := K.borderColor;
  497.     Rect(left, top, right, bottom, color);
  498.     K.CreateButton(btnCloseFind, right - 20, top, 20, 20, 0EF999FH, "");
  499.     K.DrawLine(right - 14, top + 5, right - 5, top + 14, 0FFFFFFH);
  500.     K.DrawLine(right - 15, top + 5, right - 5, top + 15, 0FFFFFFH);
  501.     K.DrawLine(right - 15, top + 6, right - 6, top + 15, 0FFFFFFH);
  502.     K.DrawLine(right - 15, top + 14, right - 6, top + 5, 0FFFFFFH);
  503.     K.DrawLine(right - 15, top + 15, right - 5, top + 5, 0FFFFFFH);
  504.     K.DrawLine(right - 14, top + 15, right - 5, top + 6, 0FFFFFFH);
  505.  
  506.     K.CreateButton(btnHideFind, right - 40, top, 20, 20, K.btnColor, "");
  507.     K.DrawLine(right - 34, top + 14, right - 26, top + 14, K.btnTextColor);
  508.     K.DrawLine(right - 34, top + 15, right - 26, top + 15, K.btnTextColor);
  509.  
  510.     INC(top, 15);
  511.     INC(left, SEARCH_PADDING);
  512.     K.DrawText866(left, top, K.textColor, "find");
  513.     K.DrawText866(left, top + 55, K.textColor, "replace with");
  514.     K.DrawText866(left, top + 330, K.textColor, "go to line");
  515.     BKW.top_s := BKW.top_s MOD 65536 + (top + 110) * 65536;
  516.     CS.top_s := CS.top_s MOD 65536 + (top + 140) * 65536;
  517.     WH.top_s := WH.top_s MOD 65536 + (top + 170) * 65536;
  518.     BKW.left_s := BKW.left_s MOD 65536 + left * 65536;
  519.     CS.left_s := CS.left_s MOD 65536 + left * 65536;
  520.     WH.left_s := WH.left_s MOD 65536 + left * 65536;
  521.     FindEdit.top := top + 20;
  522.     ReplaceEdit.top := top + 75;
  523.     GotoEdit.top := top + 350;
  524.     FindEdit.left := left;
  525.     ReplaceEdit.left := left;
  526.     GotoEdit.left := left;
  527.     box_lib.edit_box_draw(FindEdit);
  528.     box_lib.edit_box_draw(ReplaceEdit);
  529.     box_lib.edit_box_draw(GotoEdit);
  530.     box_lib.check_box_draw2(BKW); K.DrawText866(left + 20, top + 110, K.textColor, "backward");
  531.     box_lib.check_box_draw2(CS); K.DrawText866(left + 20, top + 140, K.textColor, "match case");
  532.     box_lib.check_box_draw2(WH); K.DrawText866(left + 20, top + 170, K.textColor, "whole word");
  533.     y := top + 200;
  534.     K.CreateButton(btnFindNext, left, y, btnWidth, btnHeight, K.btnColor, "next"); INC(y, btnHeight + 10);
  535.     K.CreateButton(btnReplace, left, y, btnWidth, btnHeight, K.btnColor, "replace"); INC(y, btnHeight + 10);
  536.     K.CreateButton(btnReplaceAll, left, y, btnWidth + 5*fontWidth - 2, btnHeight, K.btnColor, "replace all");
  537.     K.CreateButton(btnGoto, left, top + 380, btnWidth, btnHeight, K.btnColor, "go");
  538. END SearchPanel;
  539.  
  540.  
  541. PROCEDURE draw_window;
  542. VAR
  543.     width, height, x: INTEGER;
  544.  
  545.  
  546.     PROCEDURE drawToolbarBtn (id, x: INTEGER);
  547.     BEGIN
  548.         K.DrawRect(x, btnTop, toolBtnSize, toolBtnSize, K.toolbarColor);
  549.         K.DrawLine(x, btnTop + toolBtnSize, x + toolBtnSize, btnTop + toolBtnSize, K.shadowColor);
  550.         K.DrawLine(x + toolBtnSize, btnTop, x + toolBtnSize, btnTop + toolBtnSize, K.shadowColor);
  551.         K.CreateButton(id + ORD({30}), x, btnTop, toolBtnSize, toolBtnSize, K.btnColor, "");
  552.     END drawToolbarBtn;
  553.  
  554.  
  555.     PROCEDURE drawMainMenu (menu: Menu.tMenu; x: INTEGER; btn: INTEGER; caption: ARRAY OF WCHAR);
  556.     VAR
  557.         menuColor, textColor, n: INTEGER;
  558.     BEGIN
  559.         IF menu.tid # 0 THEN
  560.             menuColor := K.textColor;
  561.             textColor := K.winColor
  562.         ELSE
  563.             menuColor := K.winColor;
  564.             textColor := K.textColor
  565.         END;
  566.         n := LENGTH(caption);
  567.         K.DrawRect(x, 0, n*fontWidth + 2, MainMenuHeight, menuColor);
  568.         K.CreateButton(btn + ORD({30}), x, 0, n*fontWidth + 2, MainMenuHeight, K.btnColor, "");
  569.         K.DrawText(x + 1, (MainMenuHeight - fontHeight) DIV 2 + 1, textColor, caption)
  570.     END drawMainMenu;
  571.  
  572.  
  573. BEGIN
  574.     K.BeginDraw;
  575.     K.CreateWindow(30 + K.GetTickCount() MOD 128, 30 + K.GetTickCount() MOD 128, winWidth, winHeight, K.winColor, 73H, 0, 0, header);
  576.     IF (text # NIL) & ~K.RolledUp() THEN
  577.         IF confirm THEN
  578.                 resetTimer
  579.         END;
  580.         confirm := FALSE;
  581.         K.ClientSize(width, height);
  582.  
  583.         K.DrawRect(0, 0, width, TOP, K.winColor);
  584.         K.DrawRect(0, 0, LEFT, height, K.winColor);
  585.         K.DrawRect(LEFT + canvas.width - 1, TOP + canvas.height - 1, scrollWidth, scrollWidth, K.winColor);
  586.  
  587.         drawMainMenu(menuFile, menuFileX, btnFile, "file");
  588.         drawMainMenu(menuEdit, menuEditX, btnEdit, "edit");
  589.         drawMainMenu(menuSearch, menuSearchX, btnMenuSearch, "search");
  590.         drawMainMenu(menuEncoding, menuEncodingX, btnEncoding, "encoding");
  591.         drawMainMenu(menuView, menuViewX, btnView, "view");
  592.         drawMainMenu(menuSyntax, menuSyntaxX, btnSyntax, "syntax");
  593.         drawMainMenu(menuProgram, menuProgramX, btnProgram, "program");
  594.         drawMainMenu(menuTools, menuToolsX, btnTools, "tools");
  595.  
  596.         x := searchLeft;
  597.  
  598.         drawToolbarBtn(btnNew, x);
  599.         Icons.draw(icons, 2, x + iconPad, btnTop + iconPad);
  600.         INC(x, toolBtnSize + 5);
  601.  
  602.         drawToolbarBtn(btnOpen, x);
  603.         Icons.draw(icons, 0, x + iconPad, btnTop + iconPad);
  604.         INC(x, toolBtnSize + 5);
  605.  
  606.         drawToolbarBtn(btnSave, x);
  607.         INC(x, toolBtnSize + 5 + toolbarDelim);
  608.  
  609.         drawToolbarBtn(btnSearch, x);
  610.         Icons.draw(icons, 49, x + iconPad, btnTop + iconPad);
  611.         INC(x, toolBtnSize + 5 + toolbarDelim);
  612.  
  613.         drawToolbarBtn(btnUndo, x);
  614.         INC(x, toolBtnSize + 5);
  615.  
  616.         drawToolbarBtn(btnRedo, x);
  617.         INC(x, toolBtnSize + 5 + toolbarDelim);
  618.  
  619.         drawToolbarBtn(btnUpper, x);
  620.         INC(x, toolBtnSize + 5);
  621.  
  622.         drawToolbarBtn(btnLower, x);
  623.         INC(x, toolBtnSize + 5 + toolbarDelim);
  624.  
  625.         drawToolbarBtn(btnBuild, x);
  626.         INC(x, toolBtnSize + 5);
  627.  
  628.         drawToolbarBtn(btnRun, x);
  629.         INC(x, toolBtnSize + 5);
  630.  
  631.         toolbarIcons;
  632.  
  633.         DrawState(text, width, height);
  634.         IF search & searchOpened THEN
  635.             SearchPanel(searchLeft, TOP)
  636.         END;
  637.         Tabs.draw(tabs);
  638.         repaint
  639.     END;
  640.     K.EndDraw
  641. END draw_window;
  642.  
  643.  
  644. PROCEDURE mouse (VAR x, y: INTEGER);
  645. VAR
  646.     mouseX, mouseY,
  647.     cliX, cliY,
  648.     winX, winY: INTEGER;
  649. BEGIN
  650.     K.MousePos(mouseX, mouseY);
  651.     K.WinPos(winX, winY);
  652.     K.ClientPos(cliX, cliY);
  653.     x := mouseX - winX - cliX - LEFT;
  654.     y := mouseY - winY - cliY - TOP;
  655. END mouse;
  656.  
  657.  
  658. PROCEDURE getKBState (VAR shift, ctrl: BOOLEAN);
  659. VAR
  660.     kbState: SET;
  661. BEGIN
  662.     kbState := K.GetControlKeys();
  663.     shift := {0, 1} * kbState # {};
  664.     ctrl := {2, 3} * kbState # {};
  665. END getKBState;
  666.  
  667.  
  668. PROCEDURE stopTimer;
  669. BEGIN
  670.         T.hideCursor;
  671.     Timer.stop;
  672.     repaint;
  673.     Timer.stop
  674. END stopTimer;
  675.  
  676.  
  677. PROCEDURE OpenFile (VAR FileName: RW.tFileName; filter: ARRAY OF CHAR);
  678. BEGIN
  679.     stopTimer;
  680.     OpenDlg.SetFilter(OD, filter);
  681.     OpenDlg.Show(OD, 500, 400);
  682.     WHILE OD.status = 2 DO
  683.         K.Pause(30)
  684.     END;
  685.     IF OD.status = 1 THEN
  686.         COPY(OD.FilePath, FileName)
  687.     ELSE
  688.         FileName := ""
  689.     END;
  690.     resetTimer
  691. END OpenFile;
  692.  
  693.  
  694. PROCEDURE error (s: RW.tFileName);
  695. BEGIN
  696.     K.Run("/rd/1/@notify", s)
  697. END error;
  698.  
  699.  
  700. PROCEDURE saveError (name: RW.tFileName);
  701. VAR
  702.     s: RW.tFileName;
  703. BEGIN
  704.     s := "'cedit: error saving file ";
  705.     U.append8(s, name);
  706.     U.append8(s, "' -E");
  707.     error(s)
  708. END saveError;
  709.  
  710.  
  711. PROCEDURE saveAs (text: T.tText);
  712. VAR
  713.     fileName, name: RW.tFileName;
  714.     ext: ARRAY 8 OF CHAR;
  715. BEGIN
  716.     OD._type := OpenDlg.tsave;
  717.     U.getFileName(text.fileName, OD.FileName, U.SLASH);
  718.     IF OD.FileName = "" THEN
  719.         OD.FileName := "NewFile.";
  720.         CASE text.lang OF
  721.         |Languages.langNone:   ext := "txt"
  722.         |Languages.langC:      ext := "c"
  723.         |Languages.langFasm:   ext := "asm"
  724.         |Languages.langIni:    ext := "ini"
  725.         |Languages.langJSON:   ext := "json"
  726.         |Languages.langLua:    ext := "lua"
  727.         |Languages.langOberon: ext := "ob07"
  728.         |Languages.langPascal: ext := "pas"
  729.         END;
  730.         U.append8(OD.FileName, ext)
  731.     END;
  732.     OpenFile(fileName, EditFilter);
  733.     IF fileName # "" THEN
  734.         IF T.save(text, fileName, text.enc, RW.EOL_CRLF) THEN
  735.             T.setName(text, fileName);
  736.             U.getFileName(fileName, name, U.SLASH);
  737.             Tabs.rename(tabs, curText, name)
  738.         ELSE
  739.             saveError(fileName)
  740.         END
  741.     END
  742. END saveAs;
  743.  
  744.  
  745. PROCEDURE getIdx (text: T.tText): INTEGER;
  746. VAR
  747.     i: INTEGER;
  748. BEGIN
  749.     i := 0;
  750.     WHILE texts[i] # text DO
  751.         INC(i)
  752.     END
  753.     RETURN i
  754. END getIdx;
  755.  
  756.  
  757. PROCEDURE Switch (txt: T.tText);
  758. BEGIN
  759.     Tabs.switch(tabs, curText);
  760.     text := txt;
  761.     T.switch(txt);
  762.     switch := TRUE
  763. END Switch;
  764.  
  765.  
  766. PROCEDURE save (text: T.tText);
  767. BEGIN
  768.     IF text.modified THEN
  769.         IF text.fileName # "" THEN
  770.             IF ~T.save(text, text.fileName, text.enc, RW.EOL_CRLF) THEN
  771.                 saveError(text.fileName)
  772.             END
  773.         ELSE
  774.             curText := getIdx(text);
  775.             Switch(text);
  776.             saveAs(text)
  777.         END
  778.     END
  779. END save;
  780.  
  781.  
  782. PROCEDURE saveAll;
  783. VAR
  784.     i: INTEGER;
  785. BEGIN
  786.     i := textsCount - 1;
  787.     WHILE i >= 0 DO
  788.         IF texts[i].modified THEN
  789.             save(texts[i])
  790.         END;
  791.         DEC(i)
  792.     END;
  793. END saveAll;
  794.  
  795.  
  796. PROCEDURE insert (pos: INTEGER; txt: T.tText);
  797. VAR
  798.     i: INTEGER;
  799.     name: RW.tFileName;
  800. BEGIN
  801.     FOR i := textsCount - 1 TO pos BY -1 DO
  802.         texts[i + 1] := texts[i]
  803.     END;
  804.     texts[pos] := txt;
  805.     INC(textsCount);
  806.     curText := pos;
  807.     IF txt.fileName = "" THEN
  808.         name := "new"
  809.     ELSE
  810.         U.getFileName(txt.fileName, name, U.SLASH)
  811.     END;
  812.     Tabs.add(tabs, name);
  813.     Switch(txt)
  814. END insert;
  815.  
  816.  
  817. PROCEDURE Confirm;
  818. CONST
  819.     width  = btnWidth*2 + 30;
  820.     height = btnHeight*2 + 20;
  821.     lineColor = 808080H;
  822. VAR
  823.     left, top, right, bottom: INTEGER;
  824. BEGIN
  825.         stopTimer;
  826.     draw_window;
  827.     confirm := TRUE;
  828.     left := (canvas.width - width) DIV 2 + LEFT;
  829.     top := (canvas.height - height) DIV 2 + TOP;
  830.     right := left + width - 1;
  831.     bottom := top + height - 1;
  832.     K.DrawRect(left, top, width, height, K.winColor);
  833.     Rect(left, top, right, bottom, lineColor);
  834.     K.DrawText866(left + (width - 10*fontWidth) DIV 2, top + 10, K.textColor, "save file?");
  835.     K.CreateButton(btnYes, left + 10, top + 35, btnWidth, btnHeight, K.btnColor, "yes");
  836.     K.CreateButton(btnNo, left + 20 + btnWidth, top + 35, btnWidth, btnHeight, K.btnColor, "no");
  837. END Confirm;
  838.  
  839.  
  840. PROCEDURE Exit;
  841. BEGIN
  842.         Timer.kill;
  843.         K.Exit
  844. END Exit;
  845.  
  846.  
  847. PROCEDURE closeFile (conf: BOOLEAN; n: INTEGER);
  848. VAR
  849.     i: INTEGER;
  850. BEGIN
  851.     IF texts[n].modified & conf THEN
  852.         Confirm
  853.     ELSE
  854.         Tabs.delete(tabs, n);
  855.         FOR i := n + 1 TO textsCount - 1 DO
  856.             texts[i - 1] := texts[i]
  857.         END;
  858.         DEC(textsCount);
  859.         IF (curText = textsCount) OR (n < curText) THEN
  860.             DEC(curText)
  861.         END;
  862.         IF curText >= 0 THEN
  863.             Switch(texts[curText])
  864.         ELSE
  865.             Exit
  866.         END;
  867.         draw_window
  868.     END
  869. END closeFile;
  870.  
  871.  
  872. PROCEDURE NewFile;
  873. VAR
  874.     nov: T.tText;
  875. BEGIN
  876.     IF textsCount < maxTexts THEN
  877.         nov := T.New();
  878.         T.SetPos(nov, 0, 0);
  879.         insert(textsCount, nov)
  880.     ELSE
  881.         error("'cedit: too many files' -E")
  882.     END
  883. END NewFile;
  884.  
  885.  
  886. PROCEDURE getFileNum (fileName: RW.tFileName): INTEGER;
  887. VAR
  888.     i: INTEGER;
  889.  
  890.     PROCEDURE nameEq (name1, name2: RW.tFileName): BOOLEAN;
  891.     VAR
  892.         n1, n2: RW.tFileName;
  893.     BEGIN
  894.         n1 := name1;
  895.         n2 := name2;
  896.         U.upcase(n1);
  897.         U.upcase(n2)
  898.         RETURN n1 = n2
  899.     END nameEq;
  900.  
  901. BEGIN
  902.     i := 0;
  903.     WHILE (i < textsCount) & ~nameEq(texts[i].fileName, fileName) DO
  904.         INC(i)
  905.     END;
  906.     IF i = textsCount THEN
  907.         i := -1
  908.     END
  909.     RETURN i
  910. END getFileNum;
  911.  
  912.  
  913. PROCEDURE SwitchTab (n: INTEGER);
  914. BEGIN
  915.     curText := n;
  916.     Tabs.switch(tabs, n);
  917.     Switch(texts[n]);
  918.     resetTimer;
  919.     draw_window
  920. END SwitchTab;
  921.  
  922.  
  923. PROCEDURE open;
  924. VAR
  925.     fileName: RW.tFileName;
  926.     nov: T.tText;
  927.     err, n: INTEGER;
  928. BEGIN
  929.     IF textsCount < maxTexts THEN
  930.         OD._type := OpenDlg.topen;
  931.         OpenFile(fileName, EditFilter);
  932.         IF fileName # "" THEN
  933.             n := getFileNum(fileName);
  934.             IF n = -1 THEN
  935.                 nov := T.open(fileName, err);
  936.                 IF nov = NIL THEN
  937.                     error("'cedit: error opening file' -E")
  938.                 ELSE
  939.                     insert(textsCount, nov);
  940.                     T.SetPos(nov, 0, 0)
  941.                 END
  942.             ELSE
  943.                 SwitchTab(n)
  944.             END
  945.         END
  946.     ELSE
  947.         error("'cedit: too many files' -E")
  948.     END
  949. END open;
  950.  
  951.  
  952. PROCEDURE createEdit (left, top: INTEGER): box_lib.edit_box;
  953. VAR
  954.     edit, EditBox0: box_lib.edit_box;
  955. BEGIN
  956.     NEW(EditBox0);
  957.     EditBox0.text := K.malloc(EDITBOX_MAXCHARS + 2);
  958.     ASSERT(EditBox0.text # 0);
  959.     edit := box_lib.kolibri_new_edit_box(left, top, EditBox_Width, EDITBOX_MAXCHARS, EditBox0);
  960.     edit.flags := 4002H;
  961.     edit.text_color := 30000000H;
  962.     EditBox_SetFocus(edit, FALSE)
  963.     RETURN edit
  964. END createEdit;
  965.  
  966.  
  967. PROCEDURE createSearchForm;
  968. BEGIN
  969.     FindEdit := createEdit(searchLeft, TOP + 20);
  970.     ReplaceEdit := createEdit(searchLeft, TOP + 20 + 55);
  971.     GotoEdit := createEdit(searchLeft, TOP + 20 + 330);
  972.     GotoEdit.flags := ORD(BITS(GotoEdit.flags) + BITS(8000H));
  973.     BKW := box_lib.kolibri_new_check_box(searchLeft, TOP + 90 + 20, 16, 16, "", 8*fontWidth + 4);
  974.     CS := box_lib.kolibri_new_check_box(searchLeft, TOP + 120 + 20, 16, 16, "", 10*fontWidth + 4);
  975.     WH := box_lib.kolibri_new_check_box(searchLeft, TOP + 150 + 20, 16, 16, "", 10*fontWidth + 4);
  976. END createSearchForm;
  977.  
  978.  
  979. PROCEDURE EditBox_GetValue (edit: box_lib.edit_box; VAR s: ARRAY OF WCHAR);
  980. VAR
  981.     str: ARRAY EDITBOX_MAXCHARS + 1 OF CHAR;
  982.     i: INTEGER;
  983. BEGIN
  984.     box_lib.edit_box_get_value(edit, str);
  985.     i := 0;
  986.     WHILE str[i] # 0X DO
  987.         s[i] := WCHR(E.cp866[ORD(str[i])]);
  988.         INC(i)
  989.     END;
  990.     s[i] := 0X
  991. END EditBox_GetValue;
  992.  
  993.  
  994. PROCEDURE Search;
  995. BEGIN
  996.     search := ~search;
  997.     LEFT := searchLeft;
  998.     IF search THEN
  999.         searchOpened := TRUE;
  1000.         INC(LEFT, EditBox_Width + SEARCH_PADDING*2 + 5);
  1001.         IF T.search(text, searchText, cs, whole) THEN END
  1002.     ELSE
  1003.         IF T.search(text, "", FALSE, FALSE) THEN END
  1004.     END;
  1005.     SetFocus(FindEdit, search);
  1006.     resize;
  1007.     draw_window
  1008. END Search;
  1009.  
  1010.  
  1011. PROCEDURE click (x, y: INTEGER): INTEGER;
  1012. VAR
  1013.     scrollX, scrollY: INTEGER;
  1014.     shift, ctrl: BOOLEAN;
  1015. BEGIN
  1016.     getKBState(shift, ctrl);
  1017.     IF ~hScroll.mouse THEN
  1018.         Scroll.MouseDown(hScroll, x + LEFT, y + TOP);
  1019.         T.getScroll(text, scrollX, scrollY);
  1020.         T.scroll(text, hScroll.value - scrollX, 0);
  1021.         repaint
  1022.     END;
  1023.     IF ~vScroll.mouse THEN
  1024.         Scroll.MouseDown(vScroll, x + LEFT, y + TOP);
  1025.         T.getScroll(text, scrollX, scrollY);
  1026.         T.scroll(text, 0, vScroll.value - scrollY);
  1027.         repaint
  1028.     END;
  1029.     IF (0 <= x) & (x < canvas.width) & (0 <= y) & (y < canvas.height) THEN
  1030.         leftButton := TRUE;
  1031.         SetFocus(FindEdit, FALSE);
  1032.         IF ~shift THEN
  1033.             T.resetSelect(text)
  1034.         END;
  1035.         T.mouse(text, x, y);
  1036.         repaint
  1037.     END
  1038.     RETURN K.GetTickCount()
  1039. END click;
  1040.  
  1041.  
  1042. PROCEDURE LeftButtonUp;
  1043. BEGIN
  1044.     leftButton := FALSE;
  1045.     Scroll.MouseUp(hScroll);
  1046.     Scroll.MouseUp(vScroll)
  1047. END LeftButtonUp;
  1048.  
  1049.  
  1050. PROCEDURE Close;
  1051. VAR
  1052.     cont: BOOLEAN;
  1053. BEGIN
  1054.     closing := TRUE;
  1055.     cont := TRUE;
  1056.     WHILE (textsCount > 0) & cont DO
  1057.         IF text.modified THEN
  1058.             Confirm;
  1059.             cont := FALSE
  1060.         ELSE
  1061.             closeFile(FALSE, curText);
  1062.             repaint
  1063.         END
  1064.     END
  1065. END Close;
  1066.  
  1067.  
  1068. PROCEDURE CloseMenu;
  1069. BEGIN
  1070.     Menu.close(menuFile);
  1071.     Menu.close(menuEdit);
  1072.     Menu.close(menuSearch);
  1073.     Menu.close(menuEncoding);
  1074.     Menu.close(menuView);
  1075.     Menu.close(menuSyntax);
  1076.     Menu.close(menuProgram);
  1077.     Menu.close(menuTools);
  1078.     Menu.close(subCurLine);
  1079.     Menu.close(subIndent);
  1080.     Menu.close(subCase);
  1081.     Menu.close(subBookmark);
  1082.     Menu.close(context);
  1083. END CloseMenu;
  1084.  
  1085.  
  1086. PROCEDURE MenuItemClick (menu: Menu.tMenu; id: INTEGER);
  1087. BEGIN
  1088.     K.SendIPC(mainTID, id)
  1089. END MenuItemClick;
  1090.  
  1091.  
  1092. PROCEDURE goto;
  1093. VAR
  1094.     gotoVal: INTEGER;
  1095. BEGIN
  1096.     EditBox_GetValue(GotoEdit, gotoText);
  1097.     IF U.str2int(gotoText, gotoVal) & T.goto(text, gotoVal) THEN
  1098.         SetFocus(GotoEdit, FALSE)
  1099.     END
  1100. END goto;
  1101.  
  1102.  
  1103. PROCEDURE Script (script: ARRAY OF CHAR);
  1104. BEGIN
  1105.     IF script # "" THEN
  1106.         K.Run("/rd/1/@open", script)
  1107.     END
  1108. END Script;
  1109.  
  1110.  
  1111. PROCEDURE ShowSearchPanel;
  1112. BEGIN
  1113.     IF ~search THEN
  1114.         Search
  1115.     ELSIF ~searchOpened THEN
  1116.         search := FALSE;
  1117.         Search
  1118.     END
  1119. END ShowSearchPanel;
  1120.  
  1121.  
  1122. PROCEDURE CanvasToScreen (VAR x, y: INTEGER);
  1123. VAR
  1124.     cliX, cliY,
  1125.     winX, winY: INTEGER;
  1126. BEGIN
  1127.     K.WinPos(winX, winY);
  1128.     K.ClientPos(cliX, cliY);
  1129.     x := x + winX + cliX + LEFT;
  1130.     y := y + winY + cliY + TOP;
  1131. END CanvasToScreen;
  1132.  
  1133.  
  1134. PROCEDURE ShowMenu (menu: Menu.tMenu);
  1135. VAR
  1136.     winX, winY, cliX, cliY, x, y, i: INTEGER;
  1137.     selected, enabled: BOOLEAN;
  1138. BEGIN
  1139.     IF menu = context THEN
  1140.         mouse(x, y);
  1141.         IF ~((0 <= x) & (x < canvas.width) & (0 <= y) & (y < canvas.height)) THEN
  1142.             menu := NIL
  1143.         END
  1144.     ELSE
  1145.         K.WinPos(winX, winY);
  1146.         K.ClientPos(cliX, cliY);
  1147.         x := winX + cliX;
  1148.         y := MainMenuHeight + winY + cliY
  1149.     END;
  1150.  
  1151.     selected := T.selected(text);
  1152.  
  1153.     IF menu = menuFile THEN
  1154.         Menu.setEnabled(menu, menuSave, text.modified);
  1155.         Menu.setEnabled(menu, menuFolder, text.fileName # "");
  1156.         i := 0;
  1157.         WHILE (i < textsCount) & ~texts[i].modified DO
  1158.             INC(i)
  1159.         END;
  1160.         Menu.setEnabled(menu, menuSaveAll, i < textsCount);
  1161.         INC(x, menuFileX)
  1162.     ELSIF (menu = menuEdit) OR (menu = context) THEN
  1163.         Menu.setEnabled(menu, menuUndo, ~ChangeLog.isFirstGuard(text.edition));
  1164.         Menu.setEnabled(menu, menuRedo, ~ChangeLog.isLastGuard(text.edition));
  1165.         Menu.setEnabled(menu, menuCut, selected);
  1166.         Menu.setEnabled(menu, menuCopy, selected);
  1167.         Menu.setEnabled(menu, menuDelete, selected);
  1168.         Menu.setEnabled(menu, menuPaste, CB.available());
  1169.         IF menu = menuEdit THEN
  1170.             INC(x, menuEditX)
  1171.         ELSE
  1172.             IF y + menu.height >= canvas.height THEN
  1173.                 DEC(y, menu.height)
  1174.             END;
  1175.             IF x + menu.width >= canvas.width THEN
  1176.                 DEC(x, menu.width)
  1177.             END;
  1178.             CanvasToScreen(x, y)
  1179.         END
  1180.     ELSIF menu = menuEncoding THEN
  1181.         Menu.setCheck(menu, menuUTF8BOM, ORD(text.enc = E.UTF8BOM)*2);
  1182.         Menu.setCheck(menu, menuUTF8,    ORD(text.enc = E.UTF8)*2);
  1183.         Menu.setCheck(menu, menuCP866,   ORD(text.enc = E.CP866)*2);
  1184.         Menu.setCheck(menu, menuWin1251, ORD(text.enc = E.W1251)*2);
  1185.         INC(x, menuEncodingX)
  1186.     ELSIF menu = menuView THEN
  1187.         Menu.setCheck(menu, menuNumbers,  ORD(text.numbers));
  1188.         Menu.setCheck(menu, menuFontSize, ORD(font = font2));
  1189.         FOR i := 0 TO Ini.sections.count - 1 DO
  1190.             Menu.setCheck(menu, menuColors + i, ORD(Ini.curSectionNum = i)*2)
  1191.         END;
  1192.         INC(x, menuViewX)
  1193.     ELSIF menu = menuSyntax THEN
  1194.         Menu.setCheck(menu, menuNone,   ORD(text.lang = Languages.langNone)*2);
  1195.         Menu.setCheck(menu, menuC,      ORD(text.lang = Languages.langC)*2);
  1196.         Menu.setCheck(menu, menuFasm,   ORD(text.lang = Languages.langFasm)*2);
  1197.         Menu.setCheck(menu, menuIni,    ORD(text.lang = Languages.langIni)*2);
  1198.         Menu.setCheck(menu, menuJSON,   ORD(text.lang = Languages.langJSON)*2);
  1199.         Menu.setCheck(menu, menuLua,    ORD(text.lang = Languages.langLua)*2);
  1200.         Menu.setCheck(menu, menuOberon, ORD(text.lang = Languages.langOberon)*2);
  1201.         Menu.setCheck(menu, menuPascal, ORD(text.lang = Languages.langPascal)*2);
  1202.         INC(x, menuSyntaxX)
  1203.     ELSIF menu = menuProgram THEN
  1204.         Menu.setEnabled(menu, menuBuild, buildScript # "");
  1205.         Menu.setEnabled(menu, menuDebug, debugScript # "");
  1206.         Menu.setEnabled(menu, menuRun, runScript # "");
  1207.         INC(x, menuProgramX)
  1208.     ELSIF menu = menuTools THEN
  1209.         INC(x, menuToolsX)
  1210.     ELSIF menu = menuSearch THEN
  1211.         INC(x, menuSearchX)
  1212.     END;
  1213.  
  1214.     enabled := search & (searchText # "");
  1215.     Menu.setEnabled(menuSearch, menuFindNext, enabled);
  1216.     Menu.setEnabled(menuSearch, menuFindPrev, enabled);
  1217.  
  1218.     Menu.setEnabled(subIndent, menuIncInd, selected);
  1219.     Menu.setEnabled(subIndent, menuDecInd, selected);
  1220.  
  1221.     Menu.setEnabled(subCase, menuUpper, selected);
  1222.     Menu.setEnabled(subCase, menuLower, selected);
  1223.  
  1224.     IF menu # NIL THEN
  1225.         Timer.stop;
  1226.         IF Menu.opened(menu) THEN
  1227.             Menu.close(menu)
  1228.         END;
  1229.         Menu.open(menu, x, y)
  1230.     END;
  1231. END ShowMenu;
  1232.  
  1233.  
  1234. PROCEDURE receiveIPC;
  1235. VAR
  1236.         scrollIPC: BOOLEAN;
  1237. BEGIN
  1238.         scrollIPC := FALSE;
  1239.  
  1240.     IF IPC[0] = Timer.ID THEN
  1241.         T.toggleCursor;
  1242.         repaint;
  1243.         IPC[2] := 0
  1244.     ELSIF IPC[0] = mainTID THEN
  1245.         IF IPC[2] = Scroll.ScrollIPC THEN
  1246.                 Scroll.change(hScroll);
  1247.                 IF hScroll.Dec THEN
  1248.                         T.scroll(text, -1, 0)
  1249.                 ELSIF hScroll.Inc THEN
  1250.                                 T.scroll(text, 1, 0)
  1251.                 END;
  1252.                 Scroll.change(vScroll);
  1253.                 IF vScroll.Dec THEN
  1254.                         T.scroll(text, 0, -1)
  1255.                 ELSIF vScroll.Inc THEN
  1256.                                 T.scroll(text, 0, 1)
  1257.                 END;
  1258.                 repaint;
  1259.  
  1260.                 IF (0 IN K.MouseState()) THEN
  1261.                         WHILE (0 IN K.MouseState()) & (delay > 0) DO
  1262.                                 K.Pause(1);
  1263.                         DEC(delay)
  1264.                         END;
  1265.                         IF delay = 0 THEN
  1266.                                 IPC[0] := 0;
  1267.                                         IPC[1] := 0;
  1268.                                         scrollIPC := TRUE;
  1269.                                 Scroll.SendIPC;
  1270.                         delay := 2
  1271.                         ELSE
  1272.                                 delay := scrollDelay
  1273.                         END
  1274.                 ELSE
  1275.                         delay := scrollDelay
  1276.                         END
  1277.         END;
  1278.         IPC[2] := 0
  1279.     ELSIF ~Menu.isSender(IPC[0]) THEN
  1280.                 IPC[2] := 0
  1281.     END;
  1282.     CASE IPC[2] OF
  1283.     |0:
  1284.     |menuCut:       T.key(text, ORD("X"), FALSE, TRUE)
  1285.     |menuCopy:      T.key(text, ORD("C"), FALSE, TRUE)
  1286.     |menuPaste:     T.key(text, ORD("V"), FALSE, TRUE)
  1287.     |menuDelete:    T.key(text,       46, FALSE, FALSE)
  1288.     |menuSelectAll: T.key(text, ORD("A"), FALSE, TRUE)
  1289.  
  1290.     |menuNew:
  1291.         NewFile
  1292.     |menuOpen:
  1293.         open
  1294.     |menuSave:
  1295.         save(text);
  1296.         repaint
  1297.     |menuSaveAs:
  1298.         saveAs(text);
  1299.         repaint
  1300.     |menuSaveAll:
  1301.         saveAll;
  1302.         repaint
  1303.     |menuClose:
  1304.         closeFile(TRUE, curText)
  1305.     |menuFolder:
  1306.         K.Run("/rd/1/File Managers/Eolite", text.fileName)
  1307.     |menuExit:
  1308.         Close
  1309.     |menuUndo:
  1310.         T.undo(text);
  1311.         repaint
  1312.     |menuRedo:
  1313.         T.redo(text);
  1314.         repaint
  1315.     |menuFind:
  1316.         ShowSearchPanel;
  1317.         SetFocus(FindEdit, TRUE)
  1318.     |menuFindNext:
  1319.         notFound := ~T.findNext(text, box_lib.check_box_get_value(BKW))
  1320.     |menuFindPrev:
  1321.         notFound := ~T.findNext(text, ~box_lib.check_box_get_value(BKW))
  1322.     |menuGoto:
  1323.         ShowSearchPanel;
  1324.         SetFocus(GotoEdit, TRUE)
  1325.     |menuToggleBookmark:
  1326.         T.toggleLabel(text)
  1327.     |menuNextBookmark:
  1328.         T.gotoLabel(text, TRUE)
  1329.     |menuPrevBookmark:
  1330.         T.gotoLabel(text, FALSE)
  1331.     |menuNumbers:
  1332.         T.toggleNumbers(text)
  1333.     |menuFontSize:
  1334.         IF font = font1 THEN
  1335.             font := font2
  1336.         ELSE
  1337.             font := font1
  1338.         END;
  1339.         resize
  1340.     |menuNone:
  1341.         T.setLang(text, Languages.langNone)
  1342.     |menuC:
  1343.         T.setLang(text, Languages.langC)
  1344.     |menuFasm:
  1345.         T.setLang(text, Languages.langFasm)
  1346.     |menuIni:
  1347.         T.setLang(text, Languages.langIni)
  1348.     |menuJSON:
  1349.         T.setLang(text, Languages.langJSON)
  1350.     |menuLua:
  1351.         T.setLang(text, Languages.langLua)
  1352.     |menuOberon:
  1353.         T.setLang(text, Languages.langOberon)
  1354.     |menuPascal:
  1355.         T.setLang(text, Languages.langPascal)
  1356.     |menuBuild:
  1357.         Script(buildScript)
  1358.     |menuBuildScript:
  1359.         OpenFile(buildScript, ShellFilter)
  1360.     |menuRun:
  1361.         Script(runScript)
  1362.     |menuRunScript:
  1363.         OpenFile(runScript, ShellFilter)
  1364.     |menuDebug:
  1365.         Script(debugScript)
  1366.     |menuDebugScript:
  1367.         OpenFile(debugScript, ShellFilter)
  1368.     |menuUTF8BOM:
  1369.         text.enc := E.UTF8BOM
  1370.     |menuUTF8:
  1371.         text.enc := E.UTF8
  1372.     |menuCP866:
  1373.         text.enc := E.CP866
  1374.     |menuWin1251:
  1375.         text.enc := E.W1251
  1376.     |menuPipet:
  1377.         K.Run("/rd/1/develop/pipet", "")
  1378.     |menuBoard:
  1379.         K.Run("/rd/1/develop/board", "")
  1380.     |menuSysFunc:
  1381.         K.Run("/rd/1/docpack", "f")
  1382.     |menuColors..menuMaxColors:
  1383.         Ini.selectSection(IPC[2] - menuColors)
  1384.     |menuMoveUp:
  1385.         T.upLine(text)
  1386.     |menuMoveDown:
  1387.         T.downLine(text)
  1388.     |menuDuplicate:
  1389.         T.dupLine(text)
  1390.     |menuRemove:
  1391.         T.delLine(text)
  1392.     |menuIncInd:
  1393.         T.Indent(text, TRUE)
  1394.         |menuDecInd:
  1395.                 T.Indent(text, FALSE)
  1396.         |menuUpper:
  1397.                 T.chCase(text, TRUE)
  1398.         |menuLower:
  1399.                 T.chCase(text, FALSE)
  1400.     END;
  1401.     IF ~scrollIPC THEN
  1402.         IPC[0] := 0;
  1403.         IPC[1] := 0
  1404.     END
  1405. END receiveIPC;
  1406.  
  1407.  
  1408. PROCEDURE MenuKeyDown (menu: Menu.tMenu; key: INTEGER): BOOLEAN;
  1409. VAR
  1410.     menuItem: INTEGER;
  1411.     shift, ctrl: BOOLEAN;
  1412. BEGIN
  1413.     menuItem := -1;
  1414.     getKBState(shift, ctrl);
  1415.     IF ctrl THEN
  1416.         CASE key DIV 65536 OF
  1417.         |17: menuItem := menuClose
  1418.         |21: menuItem := menuRedo
  1419.         |30: menuItem := menuSelectAll
  1420.         |33: menuItem := menuFind
  1421.         |34: menuItem := menuGoto
  1422.         |44: menuItem := menuUndo
  1423.         |45: menuItem := menuCut
  1424.         |46: menuItem := menuCopy
  1425.         |47: menuItem := menuPaste
  1426.         |24: menuItem := menuOpen
  1427.         |31: menuItem := menuSave
  1428.         |49: menuItem := menuNew
  1429.         |67: menuItem := menuBuild
  1430.         ELSE
  1431.         END
  1432.     ELSE
  1433.         IF key DIV 65536 = 83 THEN
  1434.             menuItem := menuDelete
  1435.         ELSIF key DIV 65536 = 67 THEN
  1436.             menuItem := menuRun
  1437.         END
  1438.     END;
  1439.     IF menuItem # -1 THEN
  1440.         IF Menu.isEnabled(menu, menuItem) THEN
  1441.             MenuItemClick(menu, menuItem)
  1442.         ELSE
  1443.             menuItem := -1
  1444.         END
  1445.     END
  1446.     RETURN menuItem # -1
  1447. END MenuKeyDown;
  1448.  
  1449.  
  1450. PROCEDURE CreateContextMenu (): Menu.tMenu;
  1451. VAR
  1452.     menu: List.tList;
  1453. BEGIN
  1454.     menu := List.create(NIL);
  1455.     Menu.AddMenuItem(menu, menuUndo,      "undo         ctrl-Z");
  1456.     Menu.AddMenuItem(menu, menuRedo,      "redo         ctrl-Y");
  1457.     Menu.delimiter(menu);
  1458.     Menu.AddMenuItem(menu, menuCut,       "cut          ctrl-X");
  1459.     Menu.AddMenuItem(menu, menuCopy,      "copy         ctrl-C");
  1460.     Menu.AddMenuItem(menu, menuPaste,     "paste        ctrl-V");
  1461.     Menu.AddMenuItem(menu, menuDelete,    "delete");
  1462.     Menu.delimiter(menu);
  1463.     Menu.AddMenuItem(menu, menuSelectAll, "select all   ctrl-A");
  1464.     RETURN Menu.create(menu, MenuItemClick, MenuKeyDown)
  1465. END CreateContextMenu;
  1466.  
  1467.  
  1468. PROCEDURE CreateMenuFile (): Menu.tMenu;
  1469. VAR
  1470.     menu: List.tList;
  1471. BEGIN
  1472.     menu := List.create(NIL);
  1473.     Menu.AddMenuItem(menu, menuNew,     "new         ctrl-N");
  1474.     Menu.AddMenuItem(menu, menuOpen,    "open        ctrl-O");
  1475.     Menu.AddMenuItem(menu, menuSave,    "save        ctrl-S");
  1476.     Menu.AddMenuItem(menu, menuSaveAs,  "save as");
  1477.     Menu.AddMenuItem(menu, menuSaveAll, "save all");
  1478.     Menu.AddMenuItem(menu, menuFolder,  "folder");
  1479.     Menu.delimiter(menu);
  1480.     Menu.AddMenuItem(menu, menuClose,   "close       ctrl-W");
  1481.     Menu.delimiter(menu);
  1482.     Menu.AddMenuItem(menu, menuExit,    "exit");
  1483.     RETURN Menu.create(menu, MenuItemClick, MenuKeyDown)
  1484. END CreateMenuFile;
  1485.  
  1486.  
  1487. PROCEDURE CreateMenuEdit (): Menu.tMenu;
  1488. VAR
  1489.     menu: List.tList;
  1490. BEGIN
  1491.     menu := List.create(NIL);
  1492.     Menu.AddMenuItem(menu, menuUndo,      "undo            ctrl-Z");
  1493.     Menu.AddMenuItem(menu, menuRedo,      "redo            ctrl-Y");
  1494.     Menu.delimiter(menu);
  1495.     Menu.AddMenuItem(menu, menuCut,       "cut             ctrl-X");
  1496.     Menu.AddMenuItem(menu, menuCopy,      "copy            ctrl-C");
  1497.     Menu.AddMenuItem(menu, menuPaste,     "paste           ctrl-V");
  1498.     Menu.AddMenuItem(menu, menuDelete,    "delete");
  1499.     Menu.delimiter(menu);
  1500.     Menu.AddMenuItem(menu, menuSelectAll, "select all      ctrl-A");
  1501.     Menu.delimiter(menu);
  1502.     Menu.AddMenuItem(menu, menuCurLine,   "current line");
  1503.     Menu.child(menu, subCurLine);
  1504.     Menu.AddMenuItem(menu, menuIndent,    "indent");
  1505.     Menu.child(menu, subIndent);
  1506.     Menu.AddMenuItem(menu, menuCase,      "case");
  1507.     Menu.child(menu, subCase);
  1508.     RETURN Menu.create(menu, MenuItemClick, MenuKeyDown)
  1509. END CreateMenuEdit;
  1510.  
  1511.  
  1512. PROCEDURE CreateMenuSearch (): Menu.tMenu;
  1513. VAR
  1514.     menu: List.tList;
  1515. BEGIN
  1516.     menu := List.create(NIL);
  1517.     Menu.AddMenuItem(menu, menuFind,     "search           ctrl-F");
  1518.     Menu.AddMenuItem(menu, menuFindNext, "find next        F3");
  1519.     Menu.AddMenuItem(menu, menuFindPrev, "find previous    shift-F3");
  1520.     Menu.AddMenuItem(menu, menuGoto,     "go to line       ctrl-G");
  1521.     Menu.delimiter(menu);
  1522.     Menu.AddMenuItem(menu, menuBookmark, "bookmark");
  1523.     Menu.child(menu, subBookmark);
  1524.     RETURN Menu.create(menu, MenuItemClick, MenuKeyDown)
  1525. END CreateMenuSearch;
  1526.  
  1527.  
  1528. PROCEDURE CreateMenuEncoding (): Menu.tMenu;
  1529. VAR
  1530.     menu: List.tList;
  1531. BEGIN
  1532.     menu := List.create(NIL);
  1533.     Menu.AddMenuItem(menu, menuUTF8BOM, E.names[E.UTF8BOM]);
  1534.     Menu.AddMenuItem(menu, menuUTF8,    E.names[E.UTF8]);
  1535.     Menu.AddMenuItem(menu, menuCP866,   E.names[E.CP866]);
  1536.     Menu.AddMenuItem(menu, menuWin1251, E.names[E.W1251]);
  1537.     RETURN Menu.create(menu, MenuItemClick, MenuKeyDown)
  1538. END CreateMenuEncoding;
  1539.  
  1540.  
  1541. PROCEDURE CreateMenuView (): Menu.tMenu;
  1542. VAR
  1543.     menu: List.tList;
  1544.     colors: Ini.tSection;
  1545.     idx: INTEGER;
  1546. BEGIN
  1547.     menu := List.create(NIL);
  1548.     Menu.AddMenuItem(menu, menuNumbers, "line numbers");
  1549.     Menu.AddMenuItem(menu, menuFontSize, "x2");
  1550.     Menu.delimiter(menu);
  1551.  
  1552.     colors := Ini.sections.first(Ini.tSection);
  1553.     idx := menuColors;
  1554.     WHILE colors # NIL DO
  1555.         Menu.AddMenuItem(menu, idx, colors.name);
  1556.         INC(idx);
  1557.         colors := colors.next(Ini.tSection)
  1558.     END;
  1559.  
  1560.     RETURN Menu.create(menu, MenuItemClick, MenuKeyDown)
  1561. END CreateMenuView;
  1562.  
  1563.  
  1564. PROCEDURE CreateMenuSyntax (): Menu.tMenu;
  1565. VAR
  1566.     menu: List.tList;
  1567. BEGIN
  1568.     menu := List.create(NIL);
  1569.     Menu.AddMenuItem(menu, menuC,      "C");
  1570.     Menu.AddMenuItem(menu, menuFasm,   "Fasm");
  1571.     Menu.AddMenuItem(menu, menuIni,    "Ini");
  1572.     Menu.AddMenuItem(menu, menuJSON,   "JSON");
  1573.     Menu.AddMenuItem(menu, menuLua,    "Lua");
  1574.     Menu.AddMenuItem(menu, menuOberon, "Oberon");
  1575.     Menu.AddMenuItem(menu, menuPascal, "Pascal");
  1576.     Menu.delimiter(menu);
  1577.     Menu.AddMenuItem(menu, menuNone,   "none");
  1578.     RETURN Menu.create(menu, MenuItemClick, MenuKeyDown)
  1579. END CreateMenuSyntax;
  1580.  
  1581.  
  1582. PROCEDURE CreateMenuProgram (): Menu.tMenu;
  1583. VAR
  1584.     menu: List.tList;
  1585. BEGIN
  1586.     menu := List.create(NIL);
  1587.     Menu.AddMenuItem(menu, menuBuild,       "build    ctrl-F9");
  1588.     Menu.AddMenuItem(menu, menuBuildScript, "script");
  1589.     Menu.delimiter(menu);
  1590.     Menu.AddMenuItem(menu, menuRun,         "run           F9");
  1591.     Menu.AddMenuItem(menu, menuRunScript,   "script");
  1592.     Menu.delimiter(menu);
  1593.     Menu.AddMenuItem(menu, menuDebug,       "debug");
  1594.     Menu.AddMenuItem(menu, menuDebugScript, "script");
  1595.     RETURN Menu.create(menu, MenuItemClick, MenuKeyDown)
  1596. END CreateMenuProgram;
  1597.  
  1598.  
  1599. PROCEDURE CreateMenuTools (): Menu.tMenu;
  1600. VAR
  1601.     menu: List.tList;
  1602. BEGIN
  1603.     menu := List.create(NIL);
  1604.     Menu.AddMenuItem(menu, menuPipet,   "pipet");
  1605.     Menu.AddMenuItem(menu, menuBoard,   "board");
  1606.     Menu.AddMenuItem(menu, menuSysFunc, "system functions");
  1607.     RETURN Menu.create(menu, MenuItemClick, MenuKeyDown)
  1608. END CreateMenuTools;
  1609.  
  1610.  
  1611. PROCEDURE CreateMenuCurLine(): Menu.tMenu;
  1612. VAR
  1613.     menu: List.tList;
  1614. BEGIN
  1615.     menu := List.create(NIL);
  1616.     Menu.AddMenuItem(menu, menuMoveUp,    "move up     ctrl-Up");
  1617.     Menu.AddMenuItem(menu, menuMoveDown,  "move down   ctrl-Down");
  1618.     Menu.AddMenuItem(menu, menuDuplicate, "duplicate   ctrl-D");
  1619.     Menu.AddMenuItem(menu, menuRemove,    "remove      ctrl-Del");
  1620.     RETURN Menu.create(menu, MenuItemClick, MenuKeyDown)
  1621. END CreateMenuCurLine;
  1622.  
  1623.  
  1624. PROCEDURE CreateMenuIndent(): Menu.tMenu;
  1625. VAR
  1626.     menu: List.tList;
  1627. BEGIN
  1628.     menu := List.create(NIL);
  1629.     Menu.AddMenuItem(menu, menuIncInd, "increase    Tab");
  1630.     Menu.AddMenuItem(menu, menuDecInd, "decrease    shift-Bksp");
  1631.     RETURN Menu.create(menu, MenuItemClick, MenuKeyDown)
  1632. END CreateMenuIndent;
  1633.  
  1634.  
  1635. PROCEDURE CreateMenuCase(): Menu.tMenu;
  1636. VAR
  1637.     menu: List.tList;
  1638. BEGIN
  1639.     menu := List.create(NIL);
  1640.     Menu.AddMenuItem(menu, menuUpper, "UPPER    ctrl-U");
  1641.     Menu.AddMenuItem(menu, menuLower, "lower    ctrl-L");
  1642.     RETURN Menu.create(menu, MenuItemClick, MenuKeyDown)
  1643. END CreateMenuCase;
  1644.  
  1645.  
  1646. PROCEDURE CreateMenuBookmark(): Menu.tMenu;
  1647. VAR
  1648.     menu: List.tList;
  1649. BEGIN
  1650.     menu := List.create(NIL);
  1651.     Menu.AddMenuItem(menu, menuToggleBookmark, "toggle      ctrl-F2");
  1652.     Menu.AddMenuItem(menu, menuNextBookmark,   "next        F2");
  1653.     Menu.AddMenuItem(menu, menuPrevBookmark,   "previous    shift-F2");
  1654.     RETURN Menu.create(menu, MenuItemClick, MenuKeyDown)
  1655. END CreateMenuBookmark;
  1656.  
  1657.  
  1658. PROCEDURE KeyDown (key: INTEGER);
  1659. VAR
  1660.     keyCode: INTEGER;
  1661.     shift, ctrl: BOOLEAN;
  1662. BEGIN
  1663.     keyCode := key DIV 65536;
  1664.     getKBState(shift, ctrl);
  1665.     IF confirm THEN
  1666.         IF keyCode = 28 THEN (* Enter *)
  1667.             save(text);
  1668.             IF ~text.modified THEN
  1669.                 closeFile(FALSE, curText)
  1670.             END
  1671.         END;
  1672.         key := -1
  1673.     ELSE
  1674.         IF keyCode = 61 THEN (* F3 *)
  1675.             key := -1;
  1676.             IF search & (searchText # "") THEN
  1677.                 IF shift THEN
  1678.                     notFound := ~T.findNext(text, ~box_lib.check_box_get_value(BKW))
  1679.                 ELSE
  1680.                     notFound := ~T.findNext(text, box_lib.check_box_get_value(BKW))
  1681.                 END
  1682.             END
  1683.         ELSIF keyCode = 60 THEN (* F2 *)
  1684.             key := -1;
  1685.             IF ctrl THEN
  1686.                 T.toggleLabel(text)
  1687.             ELSE
  1688.                 T.gotoLabel(text, ~shift)
  1689.             END
  1690.         ELSIF keyCode = 67 THEN (* F9 *)
  1691.             key := -1;
  1692.             IF ctrl THEN
  1693.                 Script(buildScript)
  1694.             ELSE
  1695.                 Script(runScript)
  1696.             END
  1697.         ELSIF keyCode = 1 THEN (* Esc *)
  1698.             key := -1;
  1699.             IF search THEN
  1700.                 Search
  1701.             END
  1702.         ELSIF (keyCode = 55) & (key DIV 256 MOD 256 = 52) THEN (* PrtScn *)
  1703.             key := -1
  1704.         ELSIF (keyCode = 14) & shift THEN (* shift+Backspace *)
  1705.             key := -1;
  1706.             T.input(text, -8)
  1707.         ELSIF (keyCode = 15) & ctrl THEN (* ctrl+Tab *)
  1708.             key := -1;
  1709.             SwitchTab((curText + 1) MOD textsCount)
  1710.         ELSIF (keyCode = 33) & ctrl THEN
  1711.             key := -1;
  1712.             ShowSearchPanel;
  1713.             SetFocus(FindEdit, TRUE)
  1714.         ELSIF (keyCode = 34) & ctrl THEN
  1715.             key := -1;
  1716.             ShowSearchPanel;
  1717.             SetFocus(GotoEdit, TRUE)
  1718.         ELSE
  1719.             IF EditBox_Focus(FindEdit) THEN
  1720.                 box_lib.edit_box_key(FindEdit, key);
  1721.                 EditBox_GetValue(FindEdit, new_searchText);
  1722.                 IF new_searchText # searchText THEN
  1723.                     searchText := new_searchText;
  1724.                     notFound := ~T.search(text, searchText, cs, whole)
  1725.                 END
  1726.             ELSIF EditBox_Focus(ReplaceEdit) THEN
  1727.                 box_lib.edit_box_key(ReplaceEdit, key);
  1728.                 EditBox_GetValue(ReplaceEdit, replaceText)
  1729.             ELSIF EditBox_Focus(GotoEdit) THEN
  1730.                 IF (key DIV 256) MOD 256 = 13 THEN
  1731.                     goto
  1732.                 ELSE
  1733.                     box_lib.edit_box_key(GotoEdit, key)
  1734.                 END
  1735.             ELSE
  1736.                 CASE keyCode OF
  1737.                 |73: key := 33
  1738.                 |81: key := 34
  1739.                 |71: key := 36
  1740.                 |79: key := 35
  1741.                 |72: key := 38
  1742.                 |80: key := 40
  1743.                 |75: key := 37
  1744.                 |77: key := 39
  1745.                 |82, 91, 219, 92, 220: key := -1 (* insert, windows *)
  1746.                 |93: ShowMenu(context); key := -1
  1747.                 |83: key := 46
  1748.                 |59, 62..66, 68, 87, 88: key := -1 (* F1, F4..F8, F10, F11, F12 *)
  1749.                 ELSE
  1750.                     IF ctrl THEN
  1751.                         CASE keyCode OF
  1752.                         |17: closeFile(TRUE, curText);
  1753.                              key := -2
  1754.                         |21: T.redo(text);
  1755.                              key := -1
  1756.                         |22: key := ORD("U")
  1757.                         |24: key := -1;
  1758.                              open
  1759.                         |30: key := ORD("A")
  1760.                         |31: key := -1;
  1761.                              save(text)
  1762.                         |32: key := ORD("D")
  1763.                         |38: key := ORD("L")
  1764.                         |44: T.undo(text);
  1765.                              key := -1
  1766.                         |45: key := ORD("X")
  1767.                         |46: key := ORD("C")
  1768.                         |47: key := ORD("V")
  1769.                         |49: key := -1;
  1770.                              NewFile
  1771.                         ELSE
  1772.                             key := -1
  1773.                         END
  1774.                     ELSE
  1775.                         T.input(text, E.cp866[key DIV 256 MOD 256]);
  1776.                         key := -1
  1777.                     END
  1778.                 END;
  1779.                 IF key >= 0 THEN
  1780.                     T.key(text, key, shift, ctrl)
  1781.                 END
  1782.             END
  1783.         END
  1784.     END;
  1785.     IF key # -2 THEN
  1786.         repaint
  1787.     END
  1788. END KeyDown;
  1789.  
  1790.  
  1791. PROCEDURE BtnClick;
  1792. VAR
  1793.     btn: INTEGER;
  1794.     middle, exit: BOOLEAN;
  1795. BEGIN
  1796.     btn := K.ButtonCode(middle);
  1797.     IF (Tabs.btnID <= btn) & (btn <= Tabs.btnID + maxTexts - 1) THEN
  1798.         DEC(btn, Tabs.btnID);
  1799.         IF middle THEN
  1800.             IF texts[btn].modified THEN
  1801.                 SwitchTab(btn)
  1802.             END;
  1803.             closeFile(TRUE, btn)
  1804.         ELSE
  1805.             SwitchTab(btn)
  1806.         END;
  1807.         btn := 0
  1808.     ELSE
  1809.         IF middle THEN
  1810.             btn := 0
  1811.         END
  1812.     END;
  1813.     CASE btn OF
  1814.     |Tabs.btnID - 1: Tabs.scroll(tabs, -1); switch := TRUE; repaint
  1815.     |Tabs.btnID - 2: Tabs.scroll(tabs, +1); switch := TRUE; repaint
  1816.  
  1817.     |0:
  1818.  
  1819.     |btnFile:
  1820.         ShowMenu(menuFile)
  1821.     |btnEdit:
  1822.         ShowMenu(menuEdit)
  1823.     |btnMenuSearch:
  1824.         ShowMenu(menuSearch)
  1825.     |btnEncoding:
  1826.         ShowMenu(menuEncoding)
  1827.     |btnView:
  1828.         ShowMenu(menuView)
  1829.     |btnSyntax:
  1830.         ShowMenu(menuSyntax)
  1831.     |btnProgram:
  1832.         ShowMenu(menuProgram)
  1833.     |btnTools:
  1834.         ShowMenu(menuTools)
  1835.     |btnNo:
  1836.         exit := closing;
  1837.         closeFile(FALSE, curText);
  1838.         repaint;
  1839.         IF exit THEN
  1840.             Close
  1841.         END
  1842.     |btnYes:
  1843.         exit := closing;
  1844.         save(text);
  1845.         IF ~text.modified THEN
  1846.             closeFile(FALSE, curText)
  1847.         END;
  1848.         repaint;
  1849.         IF exit THEN
  1850.             Close
  1851.         END
  1852.     |btnClose:
  1853.         Close
  1854.     |btnNew:
  1855.         NewFile;
  1856.         repaint
  1857.     |btnOpen:
  1858.         open
  1859.     |btnSave:
  1860.         save(text);
  1861.         repaint
  1862.     |btnSearch:
  1863.         ShowSearchPanel
  1864.     |btnCloseFind:
  1865.         Search
  1866.     |btnHideFind:
  1867.         SetFocus(FindEdit, FALSE);
  1868.         searchOpened := FALSE;
  1869.         LEFT := searchLeft;
  1870.         resize;
  1871.         draw_window
  1872.     |btnUndo:
  1873.         T.undo(text);
  1874.         repaint
  1875.     |btnRedo:
  1876.         T.redo(text);
  1877.         repaint
  1878.     |btnUpper:
  1879.         T.chCase(text, TRUE);
  1880.         repaint
  1881.     |btnLower:
  1882.         T.chCase(text, FALSE);
  1883.         repaint
  1884.     |btnBuild:
  1885.         Script(buildScript)
  1886.     |btnRun:
  1887.         Script(runScript)
  1888.     |btnFindNext:
  1889.         IF searchText # "" THEN
  1890.             notFound := ~T.findNext(text, box_lib.check_box_get_value(BKW));
  1891.             repaint
  1892.         END
  1893.     |btnReplace:
  1894.         T.replace(text, replaceText, LENGTH(searchText));
  1895.         repaint
  1896.     |btnReplaceAll:
  1897.         notFound := ~T.search(text, searchText, cs, whole);
  1898.         IF ~notFound THEN
  1899.             replaced := T.replaceAll(text, replaceText, LENGTH(searchText));
  1900.         END;
  1901.         repaint
  1902.     |btnGoto:
  1903.         goto;
  1904.         repaint
  1905.     END
  1906. END BtnClick;
  1907.  
  1908.  
  1909. PROCEDURE MouseEvent (VAR resized: BOOLEAN; VAR firstClickX, firstClickY, time: INTEGER);
  1910. CONST
  1911.     DELAY = 10;
  1912. VAR
  1913.     msState: SET;
  1914.     scroll, x, y, scrollX, scrollY: INTEGER;
  1915.  
  1916.  
  1917.     PROCEDURE EditBox (eb: box_lib.edit_box);
  1918.     VAR
  1919.         focus: BOOLEAN;
  1920.     BEGIN
  1921.         focus := EditBox_Focus(eb);
  1922.         box_lib.edit_box_mouse(eb);
  1923.         IF focus # EditBox_Focus(eb) THEN
  1924.             SetFocus(eb, TRUE);
  1925.             repaint
  1926.         END
  1927.     END EditBox;
  1928.  
  1929.  
  1930. BEGIN
  1931.         CloseMenu;
  1932.     IF ~resized THEN
  1933.         msState := K.MouseState();
  1934.         IF ~(0 IN msState) OR (16 IN msState) THEN
  1935.             LeftButtonUp
  1936.         END;
  1937.         scroll := K.Scroll();
  1938.         IF scroll # 0 THEN
  1939.             T.scroll(text, 0, scroll*3);
  1940.             repaint
  1941.         END;
  1942.         IF leftButton THEN
  1943.             IF K.GetTickCount() - time >= DELAY THEN
  1944.                 mouse(x, y);
  1945.                 T.mouse(text, x, y);
  1946.                 repaint
  1947.             END
  1948.         END;
  1949.                 IF Scroll.isActive(hScroll) THEN
  1950.                         mouse(x, y);
  1951.                         Scroll.MouseMove(hScroll, x + LEFT, y + TOP);
  1952.             T.getScroll(text, scrollX, scrollY);
  1953.             T.scroll(text, hScroll.value - scrollX, 0);
  1954.                         repaint
  1955.                 END;
  1956.                 IF Scroll.isActive(vScroll) THEN
  1957.                         mouse(x, y);
  1958.                         Scroll.MouseMove(vScroll, x + LEFT, y + TOP);
  1959.             T.getScroll(text, scrollX, scrollY);
  1960.             T.scroll(text, 0, vScroll.value - scrollY);
  1961.                         repaint
  1962.                 END;
  1963.         IF (8 IN msState) & ~(24 IN msState) THEN
  1964.             mouse(firstClickX, firstClickY);
  1965.             time := click(firstClickX, firstClickY)
  1966.         END;
  1967.         IF 9 IN msState THEN
  1968.             ShowMenu(context)
  1969.         END;
  1970.         IF 24 IN msState THEN
  1971.             mouse(x, y);
  1972.                 IF ~hScroll.mouse THEN
  1973.                         Scroll.MouseDown(hScroll, x + LEFT, y + TOP)
  1974.                 END;
  1975.                 IF ~vScroll.mouse THEN
  1976.                         Scroll.MouseDown(vScroll, x + LEFT, y + TOP)
  1977.                 END;
  1978.             IF (ABS(x - firstClickX) < 5) & (ABS(y - firstClickY) < 5) THEN
  1979.                 IF (0 <= x) & (x < canvas.width) & (0 <= y) & (y < canvas.height) THEN
  1980.                     leftButton := FALSE;
  1981.                     T.selectWord(text);
  1982.                     repaint
  1983.                 END
  1984.             ELSE
  1985.                 firstClickX := x;
  1986.                 firstClickY := y;
  1987.                 time := click(firstClickX, firstClickY)
  1988.             END
  1989.         END
  1990.     END;
  1991.     IF search & searchOpened THEN
  1992.         EditBox(FindEdit);
  1993.         EditBox(ReplaceEdit);
  1994.         EditBox(GotoEdit);
  1995.         box_lib.check_box_mouse2(CS);
  1996.         box_lib.check_box_mouse2(WH);
  1997.         box_lib.check_box_mouse2(BKW);
  1998.         IF box_lib.check_box_get_value(CS) # cs THEN
  1999.             cs := ~cs;
  2000.             notFound := ~T.search(text, searchText, cs, whole);
  2001.             repaint
  2002.         END;
  2003.         IF box_lib.check_box_get_value(WH) # whole THEN
  2004.             whole := ~whole;
  2005.             notFound := ~T.search(text, searchText, cs, whole);
  2006.             repaint
  2007.         END
  2008.     END;
  2009.     resized := FALSE
  2010. END MouseEvent;
  2011.  
  2012.  
  2013. PROCEDURE Redraw (VAR resized: BOOLEAN; VAR width, height, cliWidth, cliHeight: INTEGER);
  2014. VAR
  2015.     i: INTEGER;
  2016. BEGIN
  2017.     K.GetSystemColors;
  2018.     FOR i := 0 TO 1 DO
  2019.         IF ~K.RolledUp() THEN
  2020.             K.ClientSize(width, height);
  2021.             IF (width # cliWidth) OR (height # cliHeight) THEN
  2022.                 cliWidth := width;
  2023.                 cliHeight := height;
  2024.                 resize;
  2025.                 resized := TRUE
  2026.             END;
  2027.             K.SetEventsMask({0, 1, 2, 5, 6, 31})
  2028.         ELSE
  2029.             K.SetEventsMask({0, 30, 31})
  2030.         END;
  2031.         draw_window
  2032.     END
  2033. END Redraw;
  2034.  
  2035.  
  2036. PROCEDURE main;
  2037. VAR
  2038.     err: INTEGER;
  2039.     fileName, filePath: RW.tFileName;
  2040.     width, height, cliWidth, cliHeight: INTEGER;
  2041.     resized: BOOLEAN;
  2042.     firstClickX, firstClickY, time: INTEGER;
  2043. BEGIN
  2044.         delay := scrollDelay;
  2045.     K.GetSystemColors;
  2046.     Icons.get(icons, grayIcons);
  2047.     modified := FALSE;
  2048.     switch := FALSE;
  2049.     closing := FALSE;
  2050.     textsCount := 0;
  2051.     curText := 0;
  2052.     mainTID := K.ThreadID();
  2053.     K.SetIPC(IPC);
  2054.     U.ptr2str(K.GetName(), AppPath);
  2055.     Ini.load(AppPath);
  2056.     LeftButtonUp;
  2057.     resized := FALSE;
  2058.     K.ScreenSize(winWidth, winHeight);
  2059.     winWidth := (winWidth*80) DIV 100 - (128 + 30);
  2060.     winHeight := winHeight - (128 + 30);
  2061.     winWidth := MAX(winWidth, minWinWidth);
  2062.     winHeight := MAX(winHeight, minWinHeight);
  2063.     cliWidth := winWidth;
  2064.     cliHeight := winHeight;
  2065.     LEFT := searchLeft;
  2066.     canvas := G.CreateCanvas(winWidth - (LEFT + RIGHT + 10), winHeight - (TOP + BOTTOM + 4) - K.SkinHeight());
  2067.     tabs := Tabs.create();
  2068.     Tabs.setArea(tabs, LEFT, TOP - Tabs.tabHeight, canvas.width, Tabs.tabHeight);
  2069.     font1 := G.CreateFont(1, "", {});
  2070.     font2 := G.CreateFont(2, "", {});
  2071.     font := font1;
  2072.     G.SetFont(canvas, font);
  2073.     T.init(resetTimer);
  2074.     T.setCanvas(canvas);
  2075.     U.ptr2str(K.GetCommandLine(), fileName);
  2076.     context := CreateContextMenu();
  2077.     menuFile := CreateMenuFile();
  2078.     subCurLine := CreateMenuCurLine();
  2079.     subIndent := CreateMenuIndent();
  2080.     subCase := CreateMenuCase();
  2081.     menuEdit := CreateMenuEdit();
  2082.     subCurLine.parent := menuEdit;
  2083.     subIndent.parent := menuEdit;
  2084.     subCase.parent := menuEdit;
  2085.     subBookmark := CreateMenuBookmark();
  2086.     menuSearch := CreateMenuSearch();
  2087.     subBookmark.parent := menuSearch;
  2088.     menuEncoding := CreateMenuEncoding();
  2089.     menuView := CreateMenuView();
  2090.     menuSyntax := CreateMenuSyntax();
  2091.     menuProgram := CreateMenuProgram();
  2092.     menuTools := CreateMenuTools();
  2093.  
  2094.     Ini.getSettings(buildScript, runScript, debugScript);
  2095.     IF fileName = "" THEN
  2096.         text := T.New();
  2097.         filePath := "/rd/1"
  2098.     ELSE
  2099.         text := T.open(fileName, err);
  2100.         IF text = NIL THEN
  2101.             error("'cedit: error opening file' -E");
  2102.             Exit
  2103.         ELSE
  2104.             U.getPath(fileName, filePath)
  2105.         END
  2106.     END;
  2107.     OD := OpenDlg.Create(draw_window, OpenDlg.topen, filePath, "");
  2108.     insert(0, text);
  2109.     Scroll.create(FALSE, canvas.width, scrollWidth, scrollWidth, scrollWidth, hScroll);
  2110.     Scroll.create(TRUE, scrollWidth, canvas.height, scrollWidth, scrollWidth, vScroll);
  2111.     T.resize(canvas.width, canvas.height);
  2112.     T.SetPos(text, 0, 0);
  2113.     confirm := FALSE;
  2114.     notFound := FALSE;
  2115.     search := FALSE;
  2116.     searchOpened := FALSE;
  2117.     createSearchForm;
  2118.     new_searchText := "";
  2119.     searchText := "";
  2120.     cs := FALSE;
  2121.     whole := FALSE;
  2122.     replaced := 0;
  2123.     K.SetEventsMask({0, 1, 2, 5, 6, 31});
  2124.     Menu.init(resetTimer);
  2125.     draw_window;
  2126.     Timer.create(mainTID);
  2127.     WHILE TRUE DO
  2128.         CASE K.WaitForEvent() OF
  2129.         |1: IF Menu.redraw THEN
  2130.                         Redraw(resized, width, height, cliWidth, cliHeight)
  2131.                 ELSE
  2132.                         Menu.Redraw;
  2133.                         K.CreateWindow(30 + K.GetTickCount() MOD 128, 30 + K.GetTickCount() MOD 128, winWidth, winHeight, K.winColor, 73H, 0, 0, header);
  2134.                         repaint
  2135.                 END
  2136.         |2: KeyDown(K.GetKey())
  2137.         |3: BtnClick
  2138.         |6: MouseEvent(resized, firstClickX, firstClickY, time)
  2139.         |7: receiveIPC
  2140.         END
  2141.     END
  2142. END main;
  2143.  
  2144.  
  2145. BEGIN
  2146.     main
  2147. END CEdit.