Syntax10.Scn.Fnt StampElems Alloc 28 Aug 94 FoldElems Syntax10i.Scn.Fnt Syntax10b.Scn.Fnt MODULE Find; (* HM (*-------------------------------------------------------------------------- Find.Domain ~ Specify the files in which Find.All should search for a pattern. Find.All ^ Searches the selection in the files specified with Find.Domain. Lists all lines containing the pattern. Find.Diff ^ Compares two texts starting from the two most recent selections Sets new selections at the first position where the two texts differ. --------------------------------------------------------------------------*) IMPORT Display, Files, Oberon, Viewers, MenuViewers, TextFrames, Texts; CONST stdMenu = "System.Close System.Copy System.Grow Edit.Search Edit.Store "; File = POINTER TO FileDesc; FileDesc = RECORD name: ARRAY 32 OF CHAR; next: File END; file: File; w: Texts.Writer; out: Texts.Text; PROCEDURE ScanPar (VAR s: Texts.Scanner); VAR v: Viewers.Viewer; t: Texts.Text; beg, end, time: LONGINT; BEGIN Texts.OpenScanner(s, Oberon.Par.text, Oberon.Par.pos); Texts.Scan(s); IF (s.class = Texts.Char) & (s.c = "^") THEN Oberon.GetSelection(t, beg, end, time); IF time >= 0 THEN Texts.OpenScanner(s, t, beg); Texts.Scan(s) END END ScanPar; PROCEDURE OpenViewer(name: ARRAY OF CHAR; t: Texts.Text); VAR v: MenuViewers.Viewer; x, y: INTEGER; t1: Texts.Text; menu: TextFrames.Frame; buf: Texts.Buffer; BEGIN IF Files.Old("Edit.Menu.Text") = NIL THEN menu := TextFrames.NewMenu(name, stdMenu) ELSE menu := TextFrames.NewMenu(name, ""); NEW(t1); Texts.Open(t1, "Edit.Menu.Text"); NEW(buf); Texts.OpenBuf(buf); Texts.Save(t1, 0, t1.len, buf); Texts.Append(menu.text, buf) END; Oberon.AllocateUserViewer(0, x, y); v := MenuViewers.New(menu, TextFrames.NewText(t, 0), TextFrames.menuH, x, y) END OpenViewer; PROCEDURE Search (fn: ARRAY OF CHAR; pat: ARRAY OF CHAR; m: INTEGER); CONST bufSize = 31744; (*2**15 - 1024*) CR = 0DX; TAB = 09X; textTag = 496; oldTextTag = -4095; f: Files.File; r: Files.Rider; n, pos: LONGINT; i, j, i0: INTEGER; ch, patj: CHAR; found: BOOLEAN; tab: ARRAY 265 OF SHORTINT; text: ARRAY bufSize OF CHAR; BEGIN (*----- open file *) f := Files.Old(fn); IF f = NIL THEN RETURN END; Files.Set(r, f, 0); Files.ReadInt(r, i); IF (i = textTag) OR (i = oldTextTag) THEN pos := 0; (*Files.ReadLInt(r, pos); -- modified to search also in collapsed Fold segments*) (*----- initialize tab *) Texts.WriteString(w, "--- "); Texts.WriteString(w, fn); Texts.WriteLn(w); FOR i := 0 TO 255 DO tab[i] := SHORT(m) END; FOR i := 0 TO m-2 DO tab[ORD(pat[i])] := SHORT(m - i - 1) END; patj := pat[m-1]; found := FALSE; LOOP (*----- read text[0..n-1] *) n := Files.Length(f) - pos; IF n > bufSize THEN n := bufSize END; IF n < m THEN EXIT END; Files.Set(r, f, pos); Files.ReadBytes(r, text, n); (*----- search pat in text[0..n-1] *) i := m - 1; j := i; WHILE i < n DO IF text[i] = patj THEN i0 := i; REPEAT DEC(i); DEC(j) UNTIL (j < 0) OR (text[i] # pat[j]); IF j < 0 THEN (*------ found: print result *) found := TRUE; WHILE (i >= 0) & (text[i] # CR) & (text[i] >= TAB) DO DEC(i) END; INC(i); Files.Set(r, f, pos + i); REPEAT Files.Read(r, ch); Texts.Write(w, ch); INC(i) UNTIL (ch = CR) OR (ch < TAB) OR (r.eof) ELSE i := i + tab[ORD(text[i])] END; IF i <= i0 THEN i := i0 + 1 END; j := m - 1 ELSE i := i + tab[ORD(text[i])] END END; pos := pos + i - m + 1 END; IF found THEN Texts.WriteLn(w); Texts.Append(out, w.buf) ELSE Texts.OpenWriter(w) END ELSE Texts.WriteString(w, fn); Texts.WriteString(w, " is no text file"); Texts.WriteLn(w); Texts.Append(Oberon.Log, w.buf) END Search; (* -- commands -- *) PROCEDURE Domain*; (* {filename} ~ *) VAR s: Texts.Scanner; f, last: File; BEGIN file := NIL; last := NIL; ScanPar(s); WHILE s.class = Texts.Name DO NEW(f); f.next := NIL; IF last = NIL THEN file := f ELSE last.next := f END; last := f; COPY(s.s, f.name); Texts.Scan(s); WHILE (s.class = Texts.Char) & (s.c = "/") DO Texts.Scan(s); Texts.Scan(s) END END Domain; PROCEDURE All*; (* ^ *) VAR pat: ARRAY 128 OF CHAR; m: INTEGER; f: File; PROCEDURE ReadPattern (VAR pat: ARRAY OF CHAR; VAR m: INTEGER); VAR t: Texts.Text; r: Texts.Reader; beg, end, time: LONGINT; ch: CHAR; BEGIN Oberon.GetSelection(t, beg, end, time); IF time > 0 THEN Texts.OpenReader(r, t, beg); m := 0; WHILE beg < end DO Texts.Read(r, ch); IF m < 127 THEN pat[m] := ch END; INC(m); INC(beg) END; pat[m] := 0X END; END ReadPattern; BEGIN ReadPattern(pat, m); out := TextFrames.Text(""); OpenViewer(pat, out); f := file; WHILE f # NIL DO Search(f.name, pat, m); f := f.next END All; PROCEDURE Diff*; (*- compares two texts from the last two selections; sets selection to first difference *) VAR f1, f2: TextFrames.Frame; p1, p2: LONGINT; r1, r2: Texts.Reader; ch1, ch2: CHAR; PROCEDURE GetSelection(VAR F: TextFrames.Frame; VAR pos: LONGINT); VAR time: LONGINT; v: Viewers.Viewer; x: INTEGER; f: Display.Frame; BEGIN time := -1; x := 0; F := NIL; WHILE x < Display.Width DO v := Viewers.This(x, 0); WHILE v.state > 1 DO f := v.dsc.next; WITH f: TextFrames.Frame DO IF f.hasSel & (f.time > time) THEN F := f; pos := f.selbeg.pos; time := f.time END ELSE END; v := Viewers.Next(v) END; x := x + v.W END; IF F # NIL THEN TextFrames.RemoveSelection(F); TextFrames.RemoveCaret(F) END END GetSelection; PROCEDURE ShowSelection(f: TextFrames.Frame; pos: LONGINT); VAR x: LONGINT; BEGIN IF pos > TextFrames.Pos(f, f.X + f.W - 1, f.Y) THEN x := pos - 150; IF x < 0 THEN x := 0 END; TextFrames.Show(f, x) END; TextFrames.SetSelection(f, pos, pos+1) END ShowSelection; BEGIN GetSelection(f1, p1); GetSelection(f2, p2); IF (f1 # NIL) & (f2 # NIL) THEN Texts.OpenReader(r1, f1.text, p1); Texts.OpenReader(r2, f2.text, p2); REPEAT Texts.Read(r1, ch1); INC(p1); Texts.Read(r2, ch2); INC(p2); UNTIL (ch1 # ch2) OR (ch1 = 0X); IF (ch1 = 0X) OR (ch2 = 0X) THEN DEC(p1); DEC(p2) END; ShowSelection(f1, p1-1); ShowSelection(f2, p2-1) END Diff; BEGIN file := NIL; Texts.OpenWriter(w) END Find. (*-------------------------------------------------------------------------- Find.Domain ~ Specify the files in which Find.All should search for a pattern. Find.All ^ Searches the selection in the files specified with Find.Domain. Lists all lines containing the pattern. Find.Diff ^ Compares two texts starting from the two most recent selections Sets new selections at the first position where the two texts differ. --------------------------------------------------------------------------*)