Ver código fonte

Search functionality

Arthur Yefimov 3 anos atrás
pai
commit
555c7d82e0
7 arquivos alterados com 178 adições e 23 exclusões
  1. 3 0
      Data/Texts/en.dat
  2. 3 0
      Data/Texts/ru.dat
  3. 92 2
      src/Editor.Mod
  4. 48 13
      src/EditorText.Mod
  5. 27 5
      src/FreeOberon.Mod
  6. 4 2
      src/Strings.Mod
  7. 1 1
      src/edit.sh

+ 3 - 0
Data/Texts/en.dat

@@ -232,6 +232,7 @@ menuAsciiTable "Ascii &table"
 menuOptions "&Options"
 menuOptions "&Options"
 menuMode "Mode&..."
 menuMode "Mode&..."
 menuNormalMode "Normal"
 menuNormalMode "Normal"
+menuLanguage "L&anguage..."
 menuCompiler "&Compiler..."
 menuCompiler "&Compiler..."
 menuMemorySizes "&Memory sizes..."
 menuMemorySizes "&Memory sizes..."
 menuLinker "&Linker..."
 menuLinker "&Linker..."
@@ -276,6 +277,7 @@ btnLocalMenu "Local menu"
 
 
 titleAbout "About"
 titleAbout "About"
 titleFreeOberon "Free Oberon"
 titleFreeOberon "Free Oberon"
+titleFind "Find"
 version "version"
 version "version"
 copyright "Copyright (c)"
 copyright "Copyright (c)"
 copyrightBy "by"
 copyrightBy "by"
@@ -291,6 +293,7 @@ titleOpenAFile "Open a File"
 labelSaveFileAs "&Save file as"
 labelSaveFileAs "&Save file as"
 labelName "&Name"
 labelName "&Name"
 labelFiles "&Files"
 labelFiles "&Files"
+labelTextToFind "&Text to find"
 
 
 pressAnyKeyToReturnToIde "Press any key to return to IDE"
 pressAnyKeyToReturnToIde "Press any key to return to IDE"
 runtimeError "Runtime error"
 runtimeError "Runtime error"

+ 3 - 0
Data/Texts/ru.dat

@@ -232,6 +232,7 @@ menuAsciiTable "&Таблица Ascii"
 menuOptions "&Опции"
 menuOptions "&Опции"
 menuMode "Режим&..."
 menuMode "Режим&..."
 menuNormalMode "Норма"
 menuNormalMode "Норма"
+menuLanguage "&Язык..."
 menuCompiler "&Компилятор..."
 menuCompiler "&Компилятор..."
 menuMemorySizes "&Размеры памяти..."
 menuMemorySizes "&Размеры памяти..."
 menuLinker "&Компоновщик..."
 menuLinker "&Компоновщик..."
@@ -275,6 +276,7 @@ btnLocalMenu "Местное меню"
 
 
 titleAbout "О программе"
 titleAbout "О программе"
 titleFreeOberon "Фри Оберон"
 titleFreeOberon "Фри Оберон"
+titleFind "Поиск"
 version "версия"
 version "версия"
 copyright "Copyright (c)"
 copyright "Copyright (c)"
 copyrightBy ""
 copyrightBy ""
@@ -290,6 +292,7 @@ titleOpenAFile "Открыть файл"
 labelSaveFileAs "&Сохранить файл как"
 labelSaveFileAs "&Сохранить файл как"
 labelName "&Имя"
 labelName "&Имя"
 labelFiles "&Файлы"
 labelFiles "&Файлы"
+labelTextToFind "Искать &текст"
 
 
 pressAnyKeyToReturnToIde "Нажмите любую клавишу, чтобы вернуться в среду"
 pressAnyKeyToReturnToIde "Нажмите любую клавишу, чтобы вернуться в среду"
 runtimeError "Ошибка времени выполнения"
 runtimeError "Ошибка времени выполнения"

+ 92 - 2
src/Editor.Mod

@@ -63,14 +63,23 @@ TYPE
   EditorDesc* = RECORD(OV.WindowDesc)
   EditorDesc* = RECORD(OV.WindowDesc)
     text*: Text.Text;
     text*: Text.Text;
     fname*: ARRAY 1000 OF CHAR;
     fname*: ARRAY 1000 OF CHAR;
+    search*: ARRAY 256 OF CHAR; (* Search string *)
     msgShown*: INTEGER; (* 0 - hidden, 1 - top, 2 - bottom *)
     msgShown*: INTEGER; (* 0 - hidden, 1 - top, 2 - bottom *)
     msg*: ARRAY 256 OF CHAR
     msg*: ARRAY 256 OF CHAR
   END;
   END;
 
 
+  SearchDialog* = POINTER TO SearchDialogDesc;
+  SearchDialogDesc = RECORD(OV.WindowDesc)
+    editor*: Editor;
+    edtText*: OV.Edit;
+    btnOk*, btnCancel*, btnHelp*: OV.Button
+  END;
+
 VAR
 VAR
   clipboard: ARRAY 16000 OF CHAR;
   clipboard: ARRAY 16000 OF CHAR;
   editorMethod-: OV.ControlMethod;
   editorMethod-: OV.ControlMethod;
   fileDialogMethod-: OV.ControlMethod;
   fileDialogMethod-: OV.ControlMethod;
+  searchDialogMethod-: OV.ControlMethod;
 
 
 (* FileDialog *)
 (* FileDialog *)
 
 
@@ -886,7 +895,7 @@ END HandleEnter;
 PROCEDURE InitEditor*(c: Editor);
 PROCEDURE InitEditor*(c: Editor);
 BEGIN OV.InitWindow(c); c.closeOnEsc := FALSE;
 BEGIN OV.InitWindow(c); c.closeOnEsc := FALSE;
   c.fname[0] := 0X; c.bg := 1; c.resizable := TRUE; c.caption := 'NONAME';
   c.fname[0] := 0X; c.bg := 1; c.resizable := TRUE; c.caption := 'NONAME';
-  c.text := Text.NewText(); c.msgShown := 0; c.msg[0] := 0X;
+  c.text := Text.NewText(); c.search[0] := 0X; c.msgShown := 0; c.msg[0] := 0X;
   c.do := editorMethod
   c.do := editorMethod
 END InitEditor;
 END InitEditor;
 
 
@@ -963,6 +972,12 @@ BEGIN
   END
   END
 END EditUnselect;
 END EditUnselect;
 
 
+PROCEDURE SearchNext*(e: Editor);
+VAR ok: BOOLEAN;
+BEGIN Text.FindNext(e.text, e.search, e.text.x, e.text.y, e.h - 2, ok);
+  IF ~ok THEN Text.FindNext(e.text, e.search, 0, 0, e.h - 2, ok) END
+END SearchNext;
+
 (* EditorMethod *)
 (* EditorMethod *)
 
 
 PROCEDURE PrintMsg(c: Editor);
 PROCEDURE PrintMsg(c: Editor);
@@ -1080,7 +1095,82 @@ BEGIN OV.InitWindowMethod(m);
   m.close := EditorClose
   m.close := EditorClose
 END InitEditorMethod;
 END InitEditorMethod;
 
 
+(* Search Dialog *)
+
+PROCEDURE SearchDialogOkClick*(c: OV.Control);
+VAR w: SearchDialog;
+BEGIN w := c.parent(SearchDialog);
+  Strings.Copy(w.edtText.caption, w.editor.search);
+  OV.CloseCurWindow(c);
+  IF w.editor.search[0] # 0X THEN
+    (*w.editor.text.MoveToLineCol(1, 1, w.editor.h);*)
+    SearchNext(w.editor)
+  END
+END SearchDialogOkClick;
+
+PROCEDURE InitSearchDialog*(c: SearchDialog; editor: Editor);
+VAR L: INTEGER;
+  s: FoStrings.String;
+BEGIN OV.InitWindow(c); c.do := searchDialogMethod; c.editor := editor;
+  FoStrings.Get('titleFind', c.caption);
+  c.modal := TRUE; c.w := 55; c.h := 9(*16*); OV.CenterWindow(c);
+
+  (* Text To Find Edit *)
+  c.edtText := OV.NewEdit();
+  c.edtText.do.resize(c.edtText, 3, 3, c.w - 6, 1);
+  OV.EditSetCaption(c.edtText, editor.search);
+  OV.Add(c, c.edtText);
+
+  (* OK button *)
+  FoStrings.Get('btnOk', s);
+  c.btnOk := OV.NewButton(s);
+  c.btnOk.default := TRUE;
+  c.btnOk.onClick := SearchDialogOkClick;
+  c.btnOk.do.resize(c.btnOk, c.w - 37, c.h - 3, 8, 1);
+  OV.Add(c, c.btnOk);
+
+  (* Cancel button *)
+  FoStrings.Get('btnCancel', s);
+  c.btnCancel := OV.NewButton(s);
+  c.btnCancel.onClick := OV.CloseCurWindow;
+  c.btnCancel.do.resize(c.btnCancel, c.w - 26, c.h - 3, 8, 1);
+  OV.Add(c, c.btnCancel);
+
+  (* Help button *)
+  (* FoStrings.Get('btnHelp', s);
+  c.btnHelp := OV.NewButton(s);
+  c.btnHelp.do.resize(c.btnHelp, c.w - 15, c.h - 3, 11, 1);
+  OV.Add(c, c.btnHelp) *)
+END InitSearchDialog;
+
+PROCEDURE NewSearchDialog*(editor: Editor): SearchDialog;
+VAR c: SearchDialog;
+BEGIN NEW(c); InitSearchDialog(c, editor) ;
+RETURN c END NewSearchDialog;
+
+(* SearchDialog Method *)
+
+PROCEDURE SearchDialogDraw*(c: OV.Control; x, y: INTEGER);
+VAR f: SearchDialog;
+  s: FoStrings.String;
+BEGIN f := c(SearchDialog);
+  OV.WindowDraw(c, x, y); INC(x, c.x); INC(y, c.y);
+  FoStrings.Get('labelTextToFind', s);
+  OV.PutMarkedString(x + 3, y + 2, s, 15, 14, 7, 0)
+END SearchDialogDraw;
+
+PROCEDURE SearchDialogGetFocus(c: OV.Control);
+BEGIN OV.WindowGetFocus(c)
+END SearchDialogGetFocus;
+
+PROCEDURE InitSearchDialogMethod*(m: OV.ControlMethod);
+BEGIN OV.InitWindowMethod(m);
+  m.draw := SearchDialogDraw;
+  m.getFocus := SearchDialogGetFocus
+END InitSearchDialogMethod;
+
 BEGIN
 BEGIN
   NEW(editorMethod); InitEditorMethod(editorMethod);
   NEW(editorMethod); InitEditorMethod(editorMethod);
-  NEW(fileDialogMethod); InitFileDialogMethod(fileDialogMethod)
+  NEW(fileDialogMethod); InitFileDialogMethod(fileDialogMethod);
+  NEW(searchDialogMethod); InitSearchDialogMethod(searchDialogMethod)
 END Editor.
 END Editor.

+ 48 - 13
src/EditorText.Mod

@@ -136,6 +136,27 @@ BEGIN t.selected := TRUE;
   t.selR := L.len
   t.selR := L.len
 END SelectAll;
 END SelectAll;
 
 
+PROCEDURE (t: Text) MoveToLineCol*(line, col, winH: INTEGER), NEW;
+VAR i, centerY, tx, ty: INTEGER; L: Line;
+BEGIN L := t.first; tx := 0; ty := 0; DEC(line); DEC(col);
+  WHILE (L.next # NIL) & (ty # line) DO L := L.next; INC(ty) END;
+  WHILE (L.s[tx] # 0X) & (col > 0) DO DEC(col); INC(tx) END;
+  t.x := tx; t.y := ty; t.cur := L;
+  IF (ty >= t.scrY + winH) OR (ty < t.scrY) THEN 
+    i := winH DIV 2;
+    WHILE (L.prev # NIL) & (i # 0) DO L := L.prev; DEC(i); DEC(ty) END;
+    t.scrFirst := L; t.scrY := ty
+  END
+END MoveToLineCol;
+
+PROCEDURE (t: Text) Select*(selL, selR, selT, selB, winH: INTEGER), NEW;
+VAR count: INTEGER; L: Line;
+BEGIN t.selected := TRUE;
+  t.selL := selL; t.selR := selR; t.selT := selT; t.selB := selB;
+  t.x := t.selR; t.y := t.selB;
+  t.MoveToLineCol(t.y + 1, t.x + 1, winH)
+END Select;
+
 (**Returns true if at least one whole line is selected,
 (**Returns true if at least one whole line is selected,
    but leading spaces may still be unselected*)
    but leading spaces may still be unselected*)
 PROCEDURE (t: Text) WholeLineSelected*(): BOOLEAN, NEW;
 PROCEDURE (t: Text) WholeLineSelected*(): BOOLEAN, NEW;
@@ -433,19 +454,6 @@ BEGIN success := FALSE; lf := 0; crlf := 0;
   END ;
   END ;
 RETURN success END LoadFromFile;
 RETURN success END LoadFromFile;
 
 
-PROCEDURE (t: Text) MoveToLineCol*(line, col, winH: INTEGER), NEW;
-VAR i, centerY, tx, ty: INTEGER; L: Line;
-BEGIN L := t.first; tx := 0; ty := 0; DEC(line); DEC(col);
-  WHILE (L.next # NIL) & (ty # line) DO L := L.next; INC(ty) END;
-  WHILE (L.s[tx] # 0X) & (col > 0) DO DEC(col); INC(tx) END;
-  t.x := tx; t.y := ty; t.cur := L;
-  IF (ty >= t.scrY + winH) OR (ty < t.scrY) THEN 
-    i := winH DIV 2;
-    WHILE (L.prev # NIL) & (i # 0) DO L := L.prev; DEC(i); DEC(ty) END;
-    t.scrFirst := L; t.scrY := ty
-  END
-END MoveToLineCol;
-
 PROCEDURE (t: Text) MoveToPos*(pos, winH: INTEGER), NEW;
 PROCEDURE (t: Text) MoveToPos*(pos, winH: INTEGER), NEW;
 CONST pad = 3;
 CONST pad = 3;
 VAR i, centerY: INTEGER; L: Line;
 VAR i, centerY: INTEGER; L: Line;
@@ -485,4 +493,31 @@ BEGIN
   END ;
   END ;
 RETURN k END CurCharKind;
 RETURN k END CurCharKind;
 
 
+PROCEDURE IsSubStr(IN s, where: ARRAY OF CHAR; pos: INTEGER): BOOLEAN;
+VAR i: INTEGER;
+BEGIN i := 0;
+  WHILE (s[i] # 0X) & (s[i] = where[pos]) DO INC(i); INC(pos) END ;
+RETURN s[i] = 0X END IsSubStr;
+
+PROCEDURE FindNext*(t: Text; IN find: ARRAY OF CHAR;
+    x, y, winH: INTEGER; VAR ok: BOOLEAN);
+VAR L: Line;
+  i, findLen, barX: INTEGER;
+BEGIN findLen := Strings.Length(find); ok := FALSE;
+  IF y = t.y THEN L := t.cur
+  ELSE L := t.first; i := y;
+    WHILE (L.next # NIL) & (i # 0) DO L := L.next; DEC(i) END
+  END;
+  REPEAT
+    barX := L.len - findLen + 1;
+    WHILE (x < barX) & ~IsSubStr(find, L.s, x) DO INC(x) END;
+    IF x < barX THEN
+      t.Select(x, x + findLen, y, y, winH);
+      ok := TRUE; L := NIL
+    ELSE L := L.next; INC(y); x := 0
+    END
+  UNTIL L = NIL;
+  IF ~ok THEN t.selected := FALSE END
+END FindNext;
+
 END EditorText.
 END EditorText.

+ 27 - 5
src/FreeOberon.Mod

@@ -19,7 +19,7 @@ along with Free Oberon.  If not, see <http://www.gnu.org/licenses/>.
 IMPORT T := TermBox, Files, Args, Utf8,
 IMPORT T := TermBox, Files, Args, Utf8,
        OV, Editor, Term, FoStrings, Config, Strings, Int, Out, Kernel;
        OV, Editor, Term, FoStrings, Config, Strings, Int, Out, Kernel;
 CONST
 CONST
-  version* = '1.1.0-alpha.2';
+  version* = '1.1.0-alpha.3';
   year = 2022;
   year = 2022;
 
 
   (* Direction of Selection *)
   (* Direction of Selection *)
@@ -676,6 +676,28 @@ BEGIN w := c.app.windows;
   END
   END
 END FileSave;
 END FileSave;
 
 
+PROCEDURE SearchFind(c: OV.Control);
+VAR w, e: OV.Window;
+BEGIN e := c.app.windows;
+  IF (e # NIL) & (e IS Editor.Editor) THEN
+    w := Editor.NewSearchDialog(e(Editor.Editor));
+    OV.AddWindow(app, w)
+  END
+END SearchFind;
+
+PROCEDURE SearchAgain(c: OV.Control);
+VAR e: OV.Window;
+BEGIN e := c.app.windows;
+  IF (e # NIL) & (e IS Editor.Editor) THEN
+    Editor.SearchNext(e(Editor.Editor))
+  END
+END SearchAgain;
+
+PROCEDURE OptionsLanguage(c: OV.Control);
+VAR w: OV.Window;
+BEGIN
+END OptionsLanguage;
+
 PROCEDURE SkipComment(VAR R: Files.Rider; VAR ch: CHAR; VAR s: ARRAY OF CHAR);
 PROCEDURE SkipComment(VAR R: Files.Rider; VAR ch: CHAR; VAR s: ARRAY OF CHAR);
 VAR last: CHAR;
 VAR last: CHAR;
 BEGIN last := ch; Files.ReadChar(R, ch);
 BEGIN last := ch; Files.ReadChar(R, ch);
@@ -1023,14 +1045,12 @@ BEGIN
   FoStrings.Get('menuSearch', s);
   FoStrings.Get('menuSearch', s);
   m := OV.NewMenu(s, '', 0, NIL);
   m := OV.NewMenu(s, '', 0, NIL);
   FoStrings.Get('menuFind', s);
   FoStrings.Get('menuFind', s);
-  OV.Add(m, OV.NewMenu(s, '', 0, NIL));
-  (*!TODO*) m.children.prev.status := OV.disabled;
+  OV.Add(m, OV.NewMenu(s, 'Ctrl+F', OV.hCtrlF, SearchFind));
   FoStrings.Get('menuReplace', s);
   FoStrings.Get('menuReplace', s);
   OV.Add(m, OV.NewMenu(s, '', 0, NIL));
   OV.Add(m, OV.NewMenu(s, '', 0, NIL));
   (*!TODO*) m.children.prev.status := OV.disabled;
   (*!TODO*) m.children.prev.status := OV.disabled;
   FoStrings.Get('menuSearchAgain', s);
   FoStrings.Get('menuSearchAgain', s);
-  OV.Add(m, OV.NewMenu(s, '', 0, NIL));
-  (*!TODO*) m.children.prev.status := OV.disabled;
+  OV.Add(m, OV.NewMenu(s, 'F12', OV.hF12, SearchAgain));
   OV.Add(m, OV.NewMenu('-', '', 0, NIL));
   OV.Add(m, OV.NewMenu('-', '', 0, NIL));
   FoStrings.Get('menuGoToLineNumber', s);
   FoStrings.Get('menuGoToLineNumber', s);
   OV.Add(m, OV.NewMenu(s, '', 0, NIL));
   OV.Add(m, OV.NewMenu(s, '', 0, NIL));
@@ -1084,6 +1104,8 @@ BEGIN
   FoStrings.Get('menuNormalMode', q);
   FoStrings.Get('menuNormalMode', q);
   OV.Add(m, OV.NewMenu(s, q, 0, NIL));
   OV.Add(m, OV.NewMenu(s, q, 0, NIL));
   (*!TODO*) m.children.prev.status := OV.disabled;
   (*!TODO*) m.children.prev.status := OV.disabled;
+  FoStrings.Get('menuLanguage', s);
+  OV.Add(m, OV.NewMenu(s, '', 0, OptionsLanguage));
   FoStrings.Get('menuCompiler', s);
   FoStrings.Get('menuCompiler', s);
   OV.Add(m, OV.NewMenu(s, '', 0, NIL));
   OV.Add(m, OV.NewMenu(s, '', 0, NIL));
   (*!TODO*) m.children.prev.status := OV.disabled;
   (*!TODO*) m.children.prev.status := OV.disabled;

+ 4 - 2
src/Strings.Mod

@@ -108,8 +108,10 @@ END Extract;
 
 
 PROCEDURE Copy*(IN source: ARRAY OF CHAR; VAR dest: ARRAY OF CHAR);
 PROCEDURE Copy*(IN source: ARRAY OF CHAR; VAR dest: ARRAY OF CHAR);
 VAR i, len: INTEGER;
 VAR i, len: INTEGER;
-BEGIN len := LEN(dest) - 1;
-  IF LEN(source) < LEN(dest) THEN len := LEN(source) - 1 END;
+BEGIN
+  IF LEN(source) < LEN(dest) THEN len := LEN(source) - 1
+  ELSE len := LEN(dest) - 1
+  END;
   i := 0;
   i := 0;
   WHILE (i # len) & (source[i] # 0X) DO dest[i] := source[i]; INC(i) END;
   WHILE (i # len) & (source[i] # 0X) DO dest[i] := source[i]; INC(i) END;
   dest[i] := 0X
   dest[i] := 0X

+ 1 - 1
src/edit.sh

@@ -1,2 +1,2 @@
 #!/bin/bash
 #!/bin/bash
-vim -p FreeOberon.Mod FoStrings.Mod ../Data/Texts/en.dat Texts.Mod OV.Mod TermBox.Mod Graph2.Mod Allegro5.Mod
+vim -p FreeOberon.Mod FoStrings.Mod ../Data/Texts/ru.dat Texts.Mod OV.Mod TermBox.Mod Graph2.Mod Allegro5.Mod