NASyntax10.Scn.FntBalloonElemsAlloc#Syntax10.Scn.Fnt"VersionElems" Version elements simplify the handling of multiple versions of a module in the same source file. Text pieces that differ from one version to the other are enclosed in version elements which look like angle brackets. When the user middle-clicks on the opening bracket a popup menu with a list of version names appears. Selecting one of the names replaces the bracketed text with the text that is stored for the selected version. "Beg" The opening bracket of a pair of version elements. When it is clicked at it shows a list of version names. Selecting one of these names replaces the text between the Beg and the End element with the text that is stored for this version name. "End" The closing bracket of a pair of version elements. "CheckMenu" Makes sure that the variants in the element are exactly the variants in the popup menu. "IndexOf" e.IndexOf(vers) returns the index i so that e.buf[i] is the text corresponding to vers. "TwinPos" e.TwinPos() returns the position of the corresponding right bracket of e. "SwitchTo" e.SwitchTo(vers) switches the element e to version vers. "Insert" VersionElems.Insert name Inserts a pair of version elements around the current selection. 'name' is the version name. "SetVersion" VersionElems.SetVersion name Switches all version elements in the marked text to version 'name'. "Find" VersionElems.Find Searches the next version element starting from the caret position and sets the caret to this element.StampElemsAlloc28 Jun 96@InfoElemsAllocVSyntax10.Scn.FntStampElemsAlloc28 Jun 96Uj"Title": Version elements "Author": H. Moessenboeck "Abstract": Allows a programmer to keep several versions of a module in the same file and to switch between these versions consistently. "Keywords": version handling "Version": no version "From": 28.06.96 08:30:39 "Until":  "Changes": 95-09-14 First version 96-06-28 Insert v switches all elements to version v Current version is shown in opened the popup menu of the version element SwitchTo v adds version v if not already present in the element Switches also elements in collapsed folds "Hints": This text can again contain arbitrary text elements! Syntax10b.Scn.Fnt<Syntax10i.Scn.Fnt, .  ;8FoldElemsNew#Syntax10.Scn.Fnt VAR i: INTEGER; BEGIN i := 0; WHILE (i < maxVersions) & (e.vers[i] # "") DO IF e.vers[i] = version THEN RETURN i END; INC(i) END; RETURN -1 END IndexOf; 88#Syntax10.Scn.Fnt// VAR s: Texts.Scanner; vers: ARRAY maxVersions, 32 OF CHAR; buf: ARRAY maxVersions OF Texts.Buffer; i, j: INTEGER; BEGIN Texts.OpenScanner(s, e.menu, 0); i := 0; REPEAT Texts.Scan(s); IF (i < maxVersions) & (s.class = Texts.Name) THEN COPY(s.s, vers[i]); j := e.IndexOf(s.s); IF j >= 0 THEN buf[i] := e.buf[j] ELSE NEW(buf[i]); Texts.OpenBuf(buf[i]) END; INC(i) END UNTIL s.eot; FOR j := 0 TO i-1 DO COPY(vers[j], e.vers[j]); e.buf[j] := buf[j] END; WHILE i < maxVersions DO e.vers[i] := ""; e.buf[i] := NIL; INC(i) END END CheckMenu; 8)8#Syntax10.Scn.FntBB VAR r: Texts.Reader; level: INTEGER; BEGIN Texts.OpenReader(r, Texts.ElemBase(e), Texts.ElemPos(e)+1); level := 1; LOOP Texts.ReadElem(r); IF r.eot THEN RETURN -1 ELSIF r.elem IS Beg THEN INC(level) ELSIF r.elem IS End THEN DEC(level); IF level = 0 THEN RETURN Texts.Pos(r) - 1 END END END END TwinPos; 87,8bSyntax10.Scn.Fntt8FoldElemsNew#Syntax10.Scn.Fnt VAR r: Texts.Reader; ch: CHAR; pos: LONGINT; i: INTEGER; BEGIN Texts.WriteLn(w); Texts.WriteString(w, s); pos := e.menu.len-1; Texts.OpenReader(r, e.menu, pos); Texts.Read(r, ch); IF ch # 0DX THEN INC(pos) END; Texts.Insert(e.menu, pos, w.buf); PopupElems.MeasureMenu(e); i := 0; WHILE (i < maxVersions) & (e.vers[i] # "") DO INC(i) END; IF i < maxVersions THEN COPY(s, e.vers[i]); NEW(e.buf[i]); Texts.OpenBuf(e.buf[i]) ELSE i := -1 END; RETURN i END NewVersion; 8s VAR t: Texts.Text; beg, end: LONGINT; i, j: INTEGER; PROCEDURE NewVersion (e: Beg; s: ARRAY OF CHAR): INTEGER;  BEGIN e.CheckMenu; IF version # e.cur THEN i := e.IndexOf(version); IF i < 0 THEN i := NewVersion(e, version) END; j := e.IndexOf(e.cur); IF i >= 0 THEN t := Texts.ElemBase(e); beg := Texts.ElemPos(e) + 1; end := e.TwinPos(); IF end >= 0 THEN Texts.Delete(t, beg, end); Texts.Insert(t, beg, e.buf[i]); IF j >= 0 THEN Texts.Recall(e.buf[j]) END; COPY(version, e.cur) END ELSE Out.F("-- more than max. no. of versions at pos #$", Texts.ElemPos(e)) END END END SwitchTo; 848 Syntax10.Scn.Fnt%=СpdPictElemsAlloc/H]ޡ(4vtHoOv (44HO (44`ogv (44`g (44To[v (44T[ (44losv (44ls (44NoUv (44NU (44fomv (44fm (44Zoav (w4Za (44royv (4wxov (44ry (44x (44HcOj (44HO (44`cgj (44`g (44Tc[j (44T[ (44lcsj (44ls (44NcUj (44NU (4|4fcmj (4x4fm (4t4|Zcaj (1H4xZa (4p4trcyj (1D1Hxcj (4l4pry (4h1Dx (4`4lH{O (4X4h`{g (4P4`T{[ (4H4Xl{s (4@4PN{U (484Hf{m (1@4@Z{a (4048r{y (4(1@x{ (4$40H]Od (4 4(HO (44$`]gd (44 `g (44T][d (44T[ (4 4l]sd (44ls (44 N]Ud (44NU (34f]md (34fm (33Z]ad (1(3Za (33r]yd (101(x]d (33ry (310x (33HuO| (33HO (33`ug| (33`g (33Tu[| (33T[ (33lus| (33ls (33NuU| (33NU (33fum| (33fm (33Zua| (1<3Za (33ruy| (181<xu| (33ry (318x (33HiOp (33HO (33`igp (33`g (33Ti[p (33T[ (33lisp (33ls (33NiUp (33NU (3|3fimp (3x3fm (3t3|Ziap (1,3xZa (3p3triyp (1$1,xip (3l3pry (3d1$x (3\3lHO (3T3d`g (3L3\T[ (3D3Tls (3<3LNU (343Dfm (13<Za (1L34ry (vt1x (=` xHH @$IxHH @H @ @' H]0HoOv0HO0`ogv0`g0To[v0T[0losv0ls4NoUv80NU0fomv4fm80Zoav4Za84royv80xov0ry0x0HcOj0HO0`cgj0`g0Tc[j0T[0lcsj0ls0NcUj4NU84fcmj80fm4Zcaj80Za0rcyj0xcj4ry80x0H{O0`{g0T{[0l{s0N{U0f{m0Z{a0r{y0x{0H]Od4HO84`]gd80`g0T][d0T[0l]sd0ls0N]Ud0NU0f]md0fm0Z]ad0Za0r]yd0x]d0ry4x84HuO|80HO0`ug|4`g80Tu[|0T[0lus|0ls0NuU|0NU0fum|0fm0Zua|0Za0ruy|4xu|80ry0x0HiOp0HO0`igp0`g4Ti[p84T[84lisp84ls80NiUp0NU0fimp0fm0Ziap0Za0riyp0xip0ry0x0HO0`g0T[0ls0NU0fm0Za0ry0x VAR line: ARRAY 10 OF SET; BEGIN  line[1] := {4}; line[2] := {3}; line[3] := {2}; line[4] := {1}; line[5] := {0}; line[6] := {1}; line[7] := {2}; line[8] := {3}; line[9] := {4}; begIcon := Display.NewPattern(line, 6, 9); line[1] := {1}; line[2] := {2}; line[3] := {3}; line[4] := {4}; line[5] := {5}; line[6] := {4}; line[7] := {3}; line[8] := {2}; line[9] := {1}; endIcon := Display.NewPattern(line, 6, 9); END InitIcons; 8E8#Syntax10.Scn.Fnt END NoNotify; 8>8#Syntax10.Scn.FntVV VAR r: Texts.Reader; pos: LONGINT; e: Beg; fe: FoldElems.Elem; t1: Texts.Text; BEGIN Texts.OpenReader(r, t, 0); LOOP Texts.ReadElem(r); IF r.eot THEN EXIT ELSIF r.elem IS Beg THEN pos := Texts.Pos(r) + 1; e := r.elem(Beg); e.SwitchTo(version); Texts.OpenReader(r, t, pos) ELSIF r.elem IS FoldElems.Elem THEN fe := r.elem(FoldElems.Elem); IF fe.mode = FoldElems.colLeft THEN NEW(t1); Texts.Open(t1, ""); t1.notify := NoNotify; Texts.Append(t1, fe.hidden); SwitchAll(t1, version); Texts.Delete(t1, 0, t1.len); Texts.Recall(fe.hidden) END END END END SwitchAll; 8 Syntax10m.Scn.Fnt )8Syntax10.Scn.FntdSyntax10m.Scn.FntuA ;< Syntax10i.Scn.Fnt Oj VAR e1: Beg; i: INTEGER; str: ARRAY 32 OF CHAR; s: Texts.Scanner; BEGIN WITH e: Beg DO WITH m: TextFrames.DisplayMsg DO IF ~m.prepare THEN Display.CopyPattern(Display.white, begIcon, m.X0, m.Y0+3, Display.paint) END | m: TextPrinter.PrintMsg DO IF m.prepare THEN e.W := 1 ELSE e.W := 7*pixel END | m: Texts.CopyMsg DO IF m.e = NIL THEN NEW(e1); m.e := e1 ELSE e1 := m.e(Beg) END; COPY(e.cur, e1.cur); i := 0; WHILE (i < maxVersions) & (e.vers[i] # "") DO COPY(e.vers[i], e1.vers[i]); NEW(e1.buf[i]); Texts.OpenBuf(e1.buf[i]); Texts.Copy(e.buf[i], e1.buf[i]); INC(i) END; PopupElems.Handle(e, m) | m: Texts.IdentifyMsg DO m.mod := "VersionElems"; m.proc := "AllocBeg" | m: TextFrames.TrackMsg DO IF m.keys = {MM} THEN e.CheckMenu; i := maxVersions-1; WHILE (i >= 0) & (e.vers[i] # e.cur) DO DEC(i) END; e.def := i END; PopupElems.Handle(e, m) | m: Texts.FileMsg DO PopupElems.Handle(e, m); IF m.id = Texts.load THEN Files.ReadString(m.r, e.cur); Files.ReadString(m.r, str); i := 0; WHILE str # "" DO COPY(str, e.vers[i]); Texts.Load(m.r, scratch); Texts.Delete(scratch, 0, scratch.len); NEW(e.buf[i]); Texts.Recall(e.buf[i]); INC(i); Files.ReadString(m.r, str) END; IF i < maxVersions THEN e.vers[i] := "" END ELSE (*Texts.store*) Files.WriteString(m.r, e.cur); i := 0; WHILE (i < maxVersions) & (e.vers[i] # "") DO Files.WriteString(m.r, e.vers[i]); Texts.Append(scratch, e.buf[i]); Texts.Store(m.r, scratch); Texts.Delete(scratch, 0, scratch.len); Texts.Recall(e.buf[i]); INC(i) END; Files.WriteString(m.r, "") END | m: PopupElems.ExecMsg DO Texts.OpenScanner(s, e.menu, m.pos); Texts.Scan(s); IF s.class = Texts.Name THEN SwitchAll(Texts.ElemBase(e), s.s) END ELSE PopupElems.Handle(e, m) END END END HandleBeg; 8  )8{Syntax10.Scn.FntISyntax10m.Scn.FntuA e< VAR e1: End; keys: SET; x, y: INTEGER; BEGIN WITH e: End DO WITH m: TextFrames.DisplayMsg DO IF ~m.prepare THEN Display.CopyPattern(Display.white, endIcon, m.X0, m.Y0+3, Display.paint) END | m: TextPrinter.PrintMsg DO IF m.prepare THEN e.W := 1 ELSE e.W := 7*pixel END | m: Texts.CopyMsg DO IF m.e = NIL THEN NEW(e1); m.e := e1 ELSE e1 := m.e(End) END; Texts.CopyElem(e, e1) | m: Texts.IdentifyMsg DO m.mod := "VersionElems"; m.proc := "AllocEnd" | m: TextFrames.TrackMsg DO IF m.keys = {MM} THEN REPEAT Input.Mouse(keys, x, y); Oberon.DrawCursor(Oberon.Mouse, Oberon.Arrow, x, y) UNTIL keys = {} END ELSE END END END HandleEnd; 8 8#Syntax10.Scn.FntQQ VAR e: Beg; BEGIN NEW(e); e.handle := HandleBeg; Texts.new := e END AllocBeg; 8 8#Syntax10.Scn.FntQQ VAR e: End; BEGIN NEW(e); e.handle := HandleEnd; Texts.new := e END AllocEnd; 8 8#Syntax10.Scn.Fnt VAR a: Beg; b: End; t: Texts.Text; beg, end, time: LONGINT; s: Texts.Scanner; BEGIN Oberon.GetSelection(t, beg, end, time); IF time >= 0 THEN Texts.OpenScanner(s, Oberon.Par.text, Oberon.Par.pos); Texts.Scan(s); IF s.class = Texts.Name THEN NEW(a); a.W := 7*pixel; a.H := 11*pixel; a.handle := HandleBeg; COPY(s.s, a.cur); a.vers[0] := ""; a.menu := TextFrames.Text(""); Texts.WriteString(w, s.s); Texts.Append(a.menu, w.buf); PopupElems.MeasureMenu(a); Texts.WriteElem(w, a); Texts.Insert(t, beg, w.buf); NEW(b); b.W := 7*pixel; b.H := 11*pixel; b.handle := HandleEnd; Texts.WriteElem(w, b); Texts.Insert(t, end+1, w.buf); SwitchAll(t, s.s) ELSE Out.String("-- version name must be an Oberon name$") END ELSE Out.String("-- no selection$") END END Insert; 8-MODULE VersionElems;  (* HM 14 Sep 95 /  *)  IMPORT Display, Files, Input, Texts, TextFrames, TextPrinter, Oberon, PopupElems, FoldElems, Out; CONST maxVersions = 4; pixel = LONG(10000); ML = 2; MM = 1; MR = 0; TYPE Beg* = POINTER TO BegDesc; BegDesc* = RECORD (PopupElems.ElemDesc) cur: ARRAY 32 OF CHAR; (*current version*) vers: ARRAY maxVersions, 32 OF CHAR; (*version names*) buf: ARRAY maxVersions OF Texts.Buffer (*version texts*) END; End* = POINTER TO EndDesc; EndDesc* = RECORD (Texts.ElemDesc) END; VAR begIcon, endIcon: Display.Pattern; (* x = 0, y = 3, w = 6, h = 9 *) scratch: Texts.Text; w: Texts.Writer; PROCEDURE (e: Beg) IndexOf (version: ARRAY OF CHAR): INTEGER;  PROCEDURE (e: Beg) CheckMenu;  PROCEDURE (e: Beg) TwinPos (): LONGINT;  PROCEDURE (e: Beg) SwitchTo (version: ARRAY OF CHAR);  PROCEDURE InitIcons;  PROCEDURE NoNotify (t: Texts.Text; op: INTEGER; beg, end: LONGINT);  PROCEDURE SwitchAll (t: Texts.Text; version: ARRAY OF CHAR);  PROCEDURE HandleBeg* (e: Texts.Elem; VAR m: Texts.ElemMsg);  PROCEDURE HandleEnd* (e: Texts.Elem; VAR m: Texts.ElemMsg);  PROCEDURE AllocBeg*;  PROCEDURE AllocEnd*;  PROCEDURE Insert*;  BEGIN InitIcons; Texts.OpenWriter(w); NEW(scratch); Texts.Open(scratch, ""); scratch.notify := NoNotify END VersionElems.