HSyntax10.Scn.Fnt8FoldElemsNew#Syntax10.Scn.Fnt(*------------------------------------------------------------ Compare files. Search for a literal string in a sequence of files. Search for clients and imports of a specific module. Search for elements Find.Diff ^ Compares two texts starting from the two most recent selections. Sets new selections at the first position where the two texts differ. Find.Domain {filename} ~ 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.Info ^ The selection must be of the form item = pattern where item is one of the headings in an info element (Title, Author, ...) and pattern is any character sequence up to the end of the selection. Lists all modules specified with Find.Domain containing the pattern in their info elements. Find.Elem (modname | ^) Find the next text element of kind k after the caret position. If a module name is specified, any element type declared in this module is searched for. If an element is specified as a selection, elements of this kind are searched for. Find.Clients (modname | ^) List all client modules which import module . Clients are searched in the same way as they would be searched for loading/opening. Find.Imports (modname | ^) List all modules imported by module . The modules are listed together with their keys. ------------------------------------------------------------*)Syntax10i.Scn.Fnt 8yInfoElemsAllocVSyntax10.Scn.Fnt@~StampElemsAlloc19 Aug 96J1"Title": Find "Author": HM (mainly), CS (added command Info) "Abstract": Provides you with the possibility to search for strings in several files, to search for certain text elements, to see which files are imported by several files, to see by which files several files are imported and to search several files for additional information (title, author, version, keywords etc.). "Keywords": search, import, client, additional info "Version": 1.0 "From": 28.10.94 16:40:44 "Until":  "Changes": "Hints": This text can again contain arbitrary text elements!  @~StampElemsAlloc19 Aug 96$MarkElemsAlloc=.8*Syntax10.Scn.Fnt. BEGIN Files.ReadBytes(r, i, 2) END ReadInt; 8 =/8*Syntax10.Scn.Fnt/ BEGIN Files.ReadBytes(r, i, 4) END ReadLInt; 8 X- 8#Syntax10.Scn.Fnt VAR t: Texts.Text; beg, end, time: LONGINT; r: Texts.Reader; BEGIN t := Oberon.Par.text; Texts.OpenScanner(s, t, 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; IF (s.class = Texts.Char) & (s.c = Texts.ElemChar) THEN Texts.OpenReader(r, t, beg); Texts.ReadElem(r); s.elem := r.elem END; END ScanPar; 8 X-08#Syntax10.Scn.Fnt VAR v: MenuViewers.Viewer; x, y: INTEGER; BEGIN Oberon.AllocateUserViewer(0, x, y); v := MenuViewers.New(TextFrames.NewMenu(name, "^Edit.Menu.Text"), TextFrames.NewText(t, 0), TextFrames.menuH, x, y) END OpenViewer; 8`_VersionElemsAllocBeg#Syntax10.Scn.FntPowerMac WindowsPowerMacPowerMac Windows=Syntax10.Scn.Fnt MarkElemsAllocX-Y@8FoldElemsNew#Syntax10.Scn.Fnt VAR ch: CHAR; i, dummy, entries, varentries,cmds, ptrs: INTEGER; ldummy: LONGINT; error: BOOLEAN; BEGIN Files.Set(r, f, 6); error := FALSE; ReadInt(r, varentries); ReadInt(r, entries); ReadInt(r, cmds); ReadInt(r, ptrs); ReadInt(r, dummy); ReadInt(r, imps); ReadInt(r, dummy); ReadInt(r, dummy); ReadLInt(r, ldummy); ReadInt(r, dummy); ReadInt(r, dummy); ReadLInt(r, key); REPEAT Files.Read(r, ch) UNTIL ch = 0X; (*skip name*) Files.Read(r, ch); IF ch = 08CX THEN Files.Set(r, f, Files.Pos(r) + 4*varentries ); (*skip varentries*) Files.Read(r, ch) ELSE error := TRUE END; IF ch = 082X THEN Files.Set(r, f, Files.Pos(r) + 2*entries ); (*skip entries*) Files.Read(r, ch) ELSE error := TRUE END; IF ch = 083X THEN FOR i := 1 TO cmds DO (*skip commands*) REPEAT Files.Read(r, ch) UNTIL ch = 0X; ReadInt(r, dummy) END ; Files.Read(r, ch) ELSE error := TRUE END; IF ch = 084X THEN Files.Set(r, f, Files.Pos(r) + 4*ptrs ); (*skip pointer offsets*) Files.Read(r, ch) ELSE error := TRUE END; IF error OR (ch # 085X) THEN Out.String("-- damaged object file$"); imps := 0 END END SkipToImports; 8fPROCEDURE SkipToImports(VAR r: Files.Rider; f : Files.File; VAR key: LONGINT; VAR imps : INTEGER);  X-Z8#Syntax10.Scn.Fnt22 VAR ch: CHAR; i, dummy, entries, cmds, ptrs: INTEGER; ldummy: LONGINT; BEGIN Files.Set(r, f, 6); ReadInt(r, entries); ReadInt(r, cmds); ReadInt(r, ptrs); ReadInt(r, dummy); ReadInt(r, imps); Files.Set(r, f, 30); ReadLInt(r, key); REPEAT Files.Read(r, ch) UNTIL ch = 0X; (*skip name*) Files.Set(r, f, Files.Pos(r) + 1 + 2*entries + 1); (*skip entries*) FOR i := 1 TO cmds DO (*skip commands*) REPEAT Files.Read(r, ch) UNTIL ch = 0X; ReadInt(r, dummy) END; Files.Set(r, f, Files.Pos(r) + 1 + 4*ptrs + 1) (*skip pointer offsets*) END SkipToImports; 8`_VersionElemsAllocEnd X-<8#Syntax10.Scn.Fnt44 CONST bufSize = 31744; (*2**15 - 1024*) textTag = 496; oldTextTag = -4095; VAR 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); ReadInt(r, i); IF (i = textTag) OR (i = oldTextTag) THEN pos := 0; (*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 END Search; 8 X-I8#Syntax10.Scn.Fnt__ VAR t, infoT: Texts.Text; r, infoR: Texts.Reader; ch, commentCh: CHAR; menuItem: ARRAY 16 OF CHAR; text: ARRAY 10000 OF CHAR; i: LONGINT; found: BOOLEAN; BEGIN Texts.WriteString(w, "--- "); Texts.WriteString(w, fn); Texts.WriteString(w, ", matches for "); Texts.WriteString(w, item); Texts.WriteString(w, " = "); Texts.WriteString(w, pat); Texts.WriteLn(w); found := FALSE; NEW(t); Texts.Open(t, fn); Texts.OpenReader(r, t, 0); Texts.ReadElem(r); WHILE ~r.eot DO IF r.elem IS InfoElems.Elem THEN (* InfoElem found *) infoT := r.elem(InfoElems.Elem).menu; (* get text of InfoElem *) Texts.OpenReader(infoR, infoT, 0); Texts.Read(infoR, ch); WHILE ~infoR.eot DO WHILE (~infoR.eot) & (ch # '"') & (ch # "'") DO Texts.Read(infoR, ch) END; IF ~infoR.eot THEN commentCh := ch END; Texts.Read(infoR, ch); i := 0; WHILE (~infoR.eot) & (ch # commentCh) DO menuItem[i] := ch; Texts.Read(infoR, ch); INC(i) END; menuItem[i] := 0X; WHILE (~infoR.eot) & ((ch = "'") OR (ch = '"') OR (ch = " ") OR (ch = TAB) OR (ch = ":")) DO Texts.Read(infoR, ch) END; i := 0; WHILE (~infoR.eot) & (ch # '"') & (ch # "'") & (i < LEN(text) - 1) DO IF (ch # TAB) & (ch # CR) THEN text[i] := ch; INC(i) END; Texts.Read(infoR, ch) END; text[i] := 0X; IF menuItem = item THEN IF Strings.Match(text, pat) THEN i := 0; found := TRUE; WHILE text[i] # 0X DO Texts.Write(w, text[i]); INC(i) END END END END END; Texts.ReadElem(r) END; IF found THEN Texts.WriteLn(w); Texts.Append(out, w.buf) ELSE Texts.OpenWriter(w) END END InfoSearch; 8 X-e8BSyntax10.Scn.FntSyntax10b.Scn.FntT`_VersionElemsAllocBeg#Syntax10.Scn.FntPowerMac WindowsPowerMacPowerMac Windows#Syntax10.Scn.Fnt44Out.String(d.path); Out.Char(Directories.delimiter);`_VersionElemsAllocEnd> VAR f: Files.File; r: Files.Rider; ch: CHAR; s: ARRAY 32 OF CHAR; i, j, imps: INTEGER; key: LONGINT; BEGIN IF isDir OR ~Strings.Match(name, "*.Obj") THEN RETURN END; f := Files.Old(name); IF f # NIL THEN SkipToImports(r, f, key, imps); FOR i := 1 TO imps DO ReadLInt(r, key); j := 0; REPEAT Files.Read(r, ch); s[j] := ch; INC(j) UNTIL ch = 0X; IF s = fileName THEN Out.String(" ");  Out.String(name); Out.Ln END END END END CheckObjFile; 8 ==8#Syntax10.Scn.Fnt66 VAR d, cur, startup: Directories.Directory; BEGIN d := Directories.This(path); cur := Directories.Current(); startup := Directories.Startup(); IF (d # NIL) & (d.path # cur.path) THEN Directories.Enumerate(d, CheckObjFile); IF d.path = startup.path THEN startupDone := TRUE END END END CheckObjFileCB; 8 =$ 8#Syntax10.Scn.Fnt VAR V: Viewers.Viewer; f: Display.Frame; BEGIN IF Oberon.Par.vwr.dsc = Oberon.Par.frame THEN f := Oberon.Par.frame.next; IF (f # NIL) & (f IS TextFrames.Frame) THEN RETURN f(TextFrames.Frame) ELSE RETURN NIL END ELSE V := Oberon.FocusViewer; IF (V # NIL) & (V IS MenuViewers.Viewer) & (V.dsc # NIL) THEN f := V.dsc.next; IF (f # NIL) & (f IS TextFrames.Frame) THEN RETURN f(TextFrames.Frame) ELSE RETURN NIL END ELSE RETURN NIL END END END TargetFrame; 8 =.y8CSyntax10.Scn.FntSyntax10b.Scn.FntE VAR beg, end, delta: LONGINT; BEGIN delta := 200; LOOP beg := F.org; end := TextFrames.Pos(F, F.X + F.W, F.Y); IF (beg <= pos) & (pos < end) OR (delta = 0) THEN EXIT END ; TextFrames.Show(F, pos - delta); delta := delta DIV 2 END; Oberon.PassFocus(Viewers.This(F.X, F.Y)); TextFrames.SetCaret(F, pos) END SetCaret; 8 X-Syntax10b.Scn.Fnt^8Syntax10.Scn.Fnt8FoldElemsNew#Syntax10.Scn.Fnt 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; 8>8#Syntax10.Scn.Fnt 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; 8e VAR f1, f2: TextFrames.Frame; p1, p2: LONGINT; r1, r2: Texts.Reader; ch1, ch2: CHAR; PROCEDURE GetSelection(VAR F: TextFrames.Frame; VAR pos: LONGINT);  PROCEDURE ShowSelection(f: TextFrames.Frame; pos: LONGINT);  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 END Diff; 8 X-g8#Syntax10.Scn.Fntww VAR s: Texts.Scanner; f, last: File; BEGIN file := NIL; last := NIL; ScanPar(s); WHILE (s.class = Texts.Name) OR (s.class = Texts.String) 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 END Domain; 8 X- !8Syntax10.Scn.Fntu8FoldElemsNew#Syntax10.Scn.FntII 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;8 VAR pat: ARRAY 128 OF CHAR; m: INTEGER; f: File; PROCEDURE ReadPattern (VAR pat: ARRAY OF CHAR; VAR m: INTEGER);  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 END All; 8 X-8Syntax10.Scn.FntKSyntax10i.Scn.Fnta8FoldElemsNew#Syntax10.Scn.Fnt}} VAR t: Texts.Text; r: Texts.Reader; s: Texts.Scanner; beg, end, time: LONGINT; ch: CHAR; BEGIN Oberon.GetSelection(t, beg, end, time); IF time > 0 THEN Texts.OpenScanner(s, t, beg); Texts.Scan(s); IF s.class IN {Texts.Name, Texts.String} THEN COPY(s.s, item); Texts.Scan(s); IF (s.class = Texts.Char) & (s.c = "=") THEN Texts.Scan(s); Texts.OpenReader(r, t, Texts.Pos(s) - 2); m := 0; beg := Texts.Pos(s) - 2; WHILE beg < end DO Texts.Read(r, ch); IF m < (LEN(pat) - 1) THEN pat[m] := ch END; INC(m); INC(beg) END; pat[m] := 0X END; END; END END ReadPattern;8  VAR pat: ARRAY 128 OF CHAR; item: ARRAY 16 OF CHAR; m: INTEGER; f: File; PROCEDURE ReadPattern;  BEGIN ReadPattern; out := TextFrames.Text(""); OpenViewer(pat, out); f := file; WHILE f # NIL DO InfoSearch(f.name, pat, item); f := f.next END END Info; 8 j~  8QSyntax10.Scn.FntxSyntax10b.Scn.Fntm;( VAR type: Types.Type; f: TextFrames.Frame; r: Texts.Reader; s: Texts.Scanner; i: INTEGER; beg: LONGINT; BEGIN ScanPar(s); IF (s.class = Texts.Name) & (s.line = 0) THEN i := 0; WHILE (s.s[i] # 0X) & (s.s[i] # ".") DO findinfo.mod[i] := s.s[i]; INC(i) END; findinfo.mod[i] := 0X ELSIF (s.class = Texts.Char) & (s.c = Texts.ElemChar) THEN type := Types.TypeOf(s.elem); COPY(type.module.name, findinfo.mod) END; f := TargetFrame(); IF f # NIL THEN IF f.hasCar THEN beg := f.carloc.pos ELSE beg := 0 END; Texts.OpenReader(r, f.text, beg); LOOP Texts.ReadElem(r); IF r.elem = NIL THEN TextFrames.RemoveCaret(f); EXIT END; type := Types.TypeOf(r.elem); IF type.module.name = findinfo.mod THEN SetCaret(f, Texts.Pos(r)); EXIT END END; TextFrames.RemoveSelection(f) END END Elem; 8 X-8#Syntax10.Scn.FntBB VAR i: INTEGER; cur, startup: Directories.Directory; BEGIN In.Open; In.Name(fileName); IF In.Done THEN i := Strings.Length(fileName); IF (i >= 4) & (fileName[i-4] = ".") THEN fileName[i-4] := 0X END; Out.String("modules importing "); Out.String(fileName); Out.Char(":"); Out.Ln; cur := Directories.Current(); startup := Directories.Startup(); Directories.Enumerate(cur, CheckObjFile); startupDone := cur.path = startup.path; Directories.EnumeratePaths(CheckObjFileCB); IF ~startupDone THEN Directories.Enumerate(startup, CheckObjFile) END END END Clients; 8 X-8#Syntax10.Scn.Fnt CONST TAB = 9X; VAR f: Files.File; r: Files.Rider; ch: CHAR; a: ARRAY 256 OF CHAR; i, j, dummy, dataEntries, entries, cmds, ptrs, imps: INTEGER; key: LONGINT; BEGIN In.Open; In.Name(a); IF In.Done THEN i := Strings.Length(a); IF (i >= 4) & (a[i-4] = ".") THEN a[i-4] := 0X END; Strings.Append(".Obj", a); f := Files.Old(a); IF f # NIL THEN SkipToImports(r, f, key, imps); Out.String(a); Out.Char(TAB); Out.Char("["); Out.Int(key, 0); Out.String("] imports:"); Out.Ln; FOR i := 1 TO imps DO ReadLInt(r, key); j := 0; REPEAT Files.Read(r, ch); a[j] := ch; INC(j) UNTIL ch = 0X; Out.Char(TAB); Out.String(a); Out.Char(TAB); Out.Char("["); Out.Int(key, 0); Out.Char("]"); Out.Ln END END END END Imports; 8IDocumentation MODULE Find;  (* HM/CS  *) IMPORT Display, Files, Directories, Oberon, Viewers, MenuViewers, TextFrames, Texts, In, Out, Strings, Modules, Types, InfoElems; CONST CR = 0DX; TAB = 09X; TYPE File = POINTER TO FileDesc; FileDesc = RECORD name: ARRAY 256 OF CHAR; next: File END ; FindInfo = RECORD time: LONGINT; mod: ARRAY 32 OF CHAR END ; VAR file: File; fileName: ARRAY 256 OF CHAR; w: Texts.Writer; out: Texts.Text; startupDone: BOOLEAN; (* state for CheckObjFileCB *) findinfo: FindInfo; PROCEDURE ReadInt (VAR r: Files.Rider; VAR i: INTEGER);  PROCEDURE ReadLInt (VAR r: Files.Rider; VAR i: LONGINT);  PROCEDURE ScanPar (VAR s: Texts.Scanner);  PROCEDURE OpenViewer(name: ARRAY OF CHAR; t: Texts.Text);  PROCEDURE SkipToImports (VAR r: Files.Rider; f : Files.File; VAR key: LONGINT; VAR imps : INTEGER);  PROCEDURE Search (fn: ARRAY OF CHAR; pat: ARRAY OF CHAR; m: INTEGER);  PROCEDURE InfoSearch (fn: ARRAY OF CHAR; pat: ARRAY OF CHAR; item: ARRAY OF CHAR);  PROCEDURE CheckObjFile (d: Directories.Directory; name: ARRAY OF CHAR; isDir: BOOLEAN; VAR continue: BOOLEAN);  PROCEDURE CheckObjFileCB (path: ARRAY OF CHAR; VAR continue: BOOLEAN);  PROCEDURE TargetFrame (): TextFrames.Frame; (*body frame or focus frame*)  PROCEDURE SetCaret (F: TextFrames.Frame; pos: LONGINT);  (* -- commands -- *) PROCEDURE Diff*; (** compares two texts from the last two selections; sets selection to first difference *)  PROCEDURE Domain*; (** {filename} ~ *)  PROCEDURE All*; (** ^ *)  PROCEDURE Info*; (** ^ format: item = searchPattern where item IN {"Title", "Author", "Abstract", "Keywords", "Version", "From", "Until", "Hints", "Changes"}, searchPattern must match exactly or contain asterisks *)  PROCEDURE Elem*; (** (modname | ^) *)  PROCEDURE Clients*;  PROCEDURE Imports*;  BEGIN file := NIL; findinfo.time := -1; Texts.OpenWriter(w) END Find.