Syntax10.Scn.Fnt Syntax10i.Scn.Fnt Syntax10b.Scn.Fnt MODULE ParcElems; (** CAS/MH/HM 26.5.1993 **) IMPORT SYSTEM, Input, Display, Files, Oberon, Fonts, Texts, TextFrames, TextPrinter; CONST BigEndianSet = FALSE; (* TRUE for HP-Oberon and POWERoberon *) (**StateMsg.id*) set* = 0; get* = 1; mm = TextFrames.mm; unit = TextFrames.Unit; Unit = TextPrinter.Unit; Scale = mm DIV 10; MinTabDelta = 5*mm; ParcHeight = 3*mm; ColumnGap = 7*mm; gridAdj = TextFrames.gridAdj; leftAdj = TextFrames.leftAdj; rightAdj = TextFrames.rightAdj; pageBreak = TextFrames.pageBreak; twoColumns = TextFrames.twoColumns; AdjMask = {leftAdj, rightAdj}; rightKey = 0; middleKey = 1; leftKey = 2; cancel = {rightKey, middleKey, leftKey}; black = Display.black; (*white = Display.white;*) replace = Display.replace; invert = Display.invert; SepH = 5; MargW = 5; MargH = 5; TYPE StateMsg* = RECORD (Texts.ElemMsg) id*: INTEGER; pos*: LONGINT; frame*: TextFrames.Frame; par*: Texts.Scanner; log*: Texts.Text END; W: Texts.Writer; TabMarkImage: ARRAY 6 OF SET; TabPat: LONGINT; white: SHORTINT; PROCEDURE FlipBits (s: SET): SET; VAR d: SET; i: INTEGER; BEGIN d := {}; i := 0; WHILE i < 32 DO IF i IN s THEN INCL(d, 31-i) END; INC(i); END; RETURN d END FlipBits; PROCEDURE RdSet (VAR r: Files.Rider; VAR s: SET); BEGIN Files.ReadNum(r, SYSTEM.VAL(LONGINT, s)); IF BigEndianSet THEN s := FlipBits(s) END; END RdSet; PROCEDURE WrtSet (VAR r: Files.Rider; s: SET); BEGIN IF BigEndianSet THEN s := FlipBits(s) END; Files.WriteNum(r, SYSTEM.VAL(LONGINT, s)); END WrtSet; PROCEDURE Str (s: ARRAY OF CHAR); BEGIN Texts.WriteString(W, s) END Str; PROCEDURE Int (n: LONGINT); BEGIN Texts.Write(W, " "); Texts.WriteInt(W, n, 0) END Int; PROCEDURE Ln; BEGIN Texts.WriteLn(W) END Ln; PROCEDURE Min (x, y: LONGINT): LONGINT; BEGIN IF x < y THEN RETURN x ELSE RETURN y END END Min; PROCEDURE Max (x, y: LONGINT): LONGINT; BEGIN IF x > y THEN RETURN x ELSE RETURN y END END Max; PROCEDURE Matches (VAR S: Texts.Scanner; key: ARRAY OF CHAR): BOOLEAN; VAR i: INTEGER; BEGIN i := 0; WHILE (S.s[i] # 0X) & (CAP(S.s[i]) = key[i]) DO INC(i) END; RETURN (S.class = Texts.Name) & ((key[i] = 0X) OR (i >= 3)) & (S.s[i] = 0X) END Matches; PROCEDURE GetNextInt (VAR S: Texts.Scanner; VAR units: LONGINT; lo, hi, def: LONGINT); (*constrained int w/ default*) BEGIN Texts.Scan(S); IF Matches(S, "DEFAULT") THEN S.class := Texts.Int; S.i := def; units := S.i * Scale; ELSIF S.class = Texts.Int THEN IF (S.i < lo) OR (S.i >= hi) THEN S.i := def END; units := S.i * Scale; END; END GetNextInt; PROCEDURE Grid (x: LONGINT): LONGINT; BEGIN RETURN x + (-x) MOD (1 * mm) END Grid; PROCEDURE DrawCursor (x, y: INTEGER); BEGIN Oberon.DrawCursor(Oberon.Mouse, Oberon.Arrow, x, y) END DrawCursor; PROCEDURE TrackMouse (VAR x, y: INTEGER; VAR keys, keysum: SET); BEGIN Input.Mouse(keys, x, y); DrawCursor(x, y); keysum := keysum + keys END TrackMouse; PROCEDURE FirstMark (col: SHORTINT; x, y0: INTEGER); BEGIN Display.ReplConst(col, x, y0 + SepH+1, 2, 5, Display.paint) END FirstMark; PROCEDURE FlipFirst (P: TextFrames.Parc; x0, y0: INTEGER); BEGIN Display.ReplConst(white, x0 + SHORT((P.left + P.first) DIV unit), y0 + SepH+1, 2, 5, invert) END FlipFirst; PROCEDURE MoveFirst (P: TextFrames.Parc; x0, y0, dw: INTEGER); VAR px: LONGINT; BEGIN px := Grid(LONG(dw) * unit); px := Max(px, -P.left); px := Min(px, P.W-P.left(*P.width*)-MinTabDelta); IF px # P.first THEN FlipFirst(P, x0, y0); P.first := px; FlipFirst(P, x0, y0) END END MoveFirst; PROCEDURE FlipLeft (P: TextFrames.Parc; x0, y0: INTEGER); BEGIN Display.ReplConst(white, x0 + SHORT(P.left DIV unit), y0+SepH-MargH+1, MargW, MargH, invert) END FlipLeft; PROCEDURE MoveLeft (P: TextFrames.Parc; rm: LONGINT; x0, y0, dw: INTEGER); VAR px: LONGINT; BEGIN px := Grid(LONG(dw) * unit); px := Max(px, 0); px := Min(px, rm); IF px # P.left THEN FlipLeft(P, x0, y0); P.left := px; FlipLeft(P, x0, y0) END END MoveLeft; PROCEDURE FlipRight (P: TextFrames.Parc; x0, y0: INTEGER); BEGIN Display.ReplConst(white, x0+SHORT((P.left + P.width) DIV unit) - MargW, y0+SepH-MargH+1, MargW, MargH, invert) END FlipRight; PROCEDURE MoveRight (P: TextFrames.Parc; rm: LONGINT; x0, y0, dw: INTEGER); VAR px: LONGINT; BEGIN px := Grid(LONG(dw) * unit); px := Max(px, P.left + 10*mm); px := Min(px, rm); IF px # P.left + P.width THEN FlipRight(P, x0, y0); P.width := px - P.left; FlipRight(P, x0, y0) END END MoveRight; PROCEDURE TabMark (col: SHORTINT; x, y: INTEGER); BEGIN Display.CopyPattern(col, TabPat, x, y, replace) END TabMark; PROCEDURE FlipTab (P: TextFrames.Parc; i, x0, y0: INTEGER); BEGIN Display.CopyPattern(white, TabPat, x0 + SHORT(P.tab[i] DIV unit), y0, invert) END FlipTab; PROCEDURE GrabTab (P: TextFrames.Parc; x0, y0, dw: INTEGER; VAR i: INTEGER; VAR new: BOOLEAN); CONST Gravity = 2*mm; VAR j: INTEGER; lx, px, rx: LONGINT; BEGIN i := 0; j := P.nofTabs; new := FALSE; px := Grid(LONG(dw) * unit); WHILE (i < j) & (P.tab[i] < px - Gravity) DO INC(i) END; IF i < TextFrames.MaxTabs THEN IF (i = j) OR (P.tab[i] >= px + Gravity) THEN IF i = 0 THEN lx := MinTabDelta ELSE lx := P.tab[i - 1] + MinTabDelta END; IF i = P.nofTabs THEN rx := P.width ELSE rx := P.tab[i] - MinTabDelta END; IF px < lx THEN px := lx END; IF px < rx THEN INC(P.nofTabs); new := TRUE; WHILE j > i DO P.tab[j] := P.tab[j - 1]; DEC(j) END END ELSE px := P.tab[i] END ELSE DEC(i); px := P.tab[i] END; IF ~new THEN FlipTab(P, i, x0, y0) END; P.tab[i] := px; FlipTab(P, i, x0, y0) END GrabTab; PROCEDURE MoveTab (P: TextFrames.Parc; rm: LONGINT; i, x0, y0, dw: INTEGER); VAR lx, px, rx: LONGINT; BEGIN px := Grid(LONG(dw) * unit); IF i = 0 THEN lx := MinTabDelta ELSE lx := P.tab[i - 1] + MinTabDelta END; IF i = P.nofTabs - 1 THEN rx := P.width ELSE rx := P.tab[i + 1] - MinTabDelta END; px := Max(px, lx); px := Min(px, rx); px := Min(px, rm); IF px # P.tab[i] THEN FlipTab(P, i, x0, y0); P.tab[i] := px; FlipTab(P, i, x0, y0) END END MoveTab; PROCEDURE RemoveTab (P: TextFrames.Parc; i: INTEGER); BEGIN WHILE i < P.nofTabs - 1 DO P.tab[i] := P.tab[i + 1]; INC(i) END; DEC(P.nofTabs) END RemoveTab; PROCEDURE ParcExtent* (T: Texts.Text; beg: LONGINT; VAR end: LONGINT); VAR R: Texts.Reader; BEGIN Texts.OpenReader(R, T, beg + 1); REPEAT Texts.ReadElem(R) UNTIL R.eot OR (R.elem IS TextFrames.Parc); IF R.eot THEN end := T.len ELSE end := Texts.Pos(R) - 1 END END ParcExtent; PROCEDURE ChangedParc* (P: TextFrames.Parc; beg: LONGINT); VAR T: Texts.Text; end: LONGINT; BEGIN T := Texts.ElemBase(P); ParcExtent(T, beg, end); Texts.ChangeLooks(T, beg, end, {}, NIL, 0, 0) END ChangedParc; PROCEDURE LoadParc* (P: TextFrames.Parc; VAR r: Files.Rider); VAR version, i, j, k: LONGINT; BEGIN Files.ReadNum(r, version); (*version 1*) Files.ReadNum(r, P.first); Files.ReadNum(r, P.left); Files.ReadNum(r, P.width); Files.ReadNum(r, P.lead); Files.ReadNum(r, P.lsp); Files.ReadNum(r, P.dsr); RdSet(r, P.opts); Files.ReadNum(r, i); IF i <= TextFrames.MaxTabs THEN P.nofTabs := SHORT(i) ELSE P.nofTabs := TextFrames.MaxTabs END; j := 0; WHILE j < P.nofTabs DO Files.ReadNum(r, P.tab[j]); INC(j) END; WHILE j < i DO Files.ReadNum(r, k); INC(j) END; END LoadParc; PROCEDURE StoreParc* (P: TextFrames.Parc; VAR r: Files.Rider); VAR i: INTEGER; BEGIN Files.WriteNum(r, 1); (*version 1*) Files.WriteNum(r, P.first); Files.WriteNum(r, P.left); Files.WriteNum(r, P.width); Files.WriteNum(r, P.lead); Files.WriteNum(r, P.lsp); Files.WriteNum(r, P.dsr); WrtSet(r, P.opts); Files.WriteNum(r, P.nofTabs); i := 0; WHILE i < P.nofTabs DO Files.WriteNum(r, P.tab[i]); INC(i) END END StoreParc; PROCEDURE CopyParc* (SP, DP: TextFrames.Parc); VAR i: INTEGER; BEGIN Texts.CopyElem(SP, DP); DP.first := SP.first; DP.left := SP.left; DP.width := SP.width; DP.lead := SP.lead; DP.lsp := SP.lsp; DP.dsr := SP.dsr; DP.opts := SP.opts; DP.nofTabs := SP.nofTabs; i := SP.nofTabs; WHILE i > 0 DO DEC(i); DP.tab[i] := SP.tab[i] END END CopyParc; PROCEDURE Prepare* (P: TextFrames.Parc; indent, unit: LONGINT); BEGIN P.W := 9999 * unit; P.H := ParcHeight + P.lead; IF gridAdj IN P.opts THEN INC(P.H, (-P.lead) MOD P.lsp) END END Prepare; PROCEDURE Draw* (P: TextFrames.Parc; F: Display.Frame; col: SHORTINT; x0, y0: INTEGER); VAR i, x1, px, w, w0, n: INTEGER; BEGIN x1 := x0 + SHORT(P.left DIV unit); w := SHORT(P.width DIV unit); (* width of parc *) w0 := SHORT((P.W - P.left) DIV unit); (* width of visible part of parc *) IF twoColumns IN P.opts THEN n := 2 ELSE n := 1 END; WHILE n > 0 DO DEC(n); IF w > 20 THEN i := 0; LOOP IF i = P.nofTabs THEN EXIT END; px := SHORT(x1 + P.tab[i] DIV unit); IF px > x1 + w THEN EXIT END; TabMark(col, px, y0); INC(i) END; IF pageBreak IN P.opts THEN Display.ReplConst(col, x1, y0 + SepH, w0, 1, replace) ELSE Display.ReplPatternC(F, col, Display.grey1, x1, y0 + SepH, w0, 1, x1, y0 + SepH, replace) END; Display.ReplPatternC(F, col, Display.grey1, x1, y0+SepH-MargH+1, MargW, MargH, x1, y0+SepH-MargH+1, replace); Display.ReplPatternC(F, col, Display.grey1, x1+w-MargW, y0+SepH-MargH+1, MargW, MargH, x1+w-MargW, y0+SepH-MargH+1, replace); IF ~(leftAdj IN P.opts) THEN Display.ReplConstC(F, black, x1+1, y0+SepH-MargH+2, MargW-2, MargH-2, replace); END; IF ~(rightAdj IN P.opts) THEN Display.ReplConstC(F, black, x1+w-MargW+1, y0+SepH-MargH+2, MargW-2, MargH-2, replace); END; FirstMark(col, x0 + SHORT((P.left + P.first) DIV unit), y0); WITH F: TextFrames.Frame DO (*recalc base measures for second column*) x0 := SHORT(Max( x1 + w + ColumnGap DIV unit, x0 + (F.W - F.left - F.right + ColumnGap DIV unit) DIV 2 )); x1 := x0 + SHORT(P.left DIV unit); w := SHORT(Min( (F.X + F.W - F.right) - x1, (P.W - P.left) DIV unit )) END END END END Draw; PROCEDURE Edit* (P: TextFrames.Parc; F: TextFrames.Frame; pos: LONGINT; x0, y0, x, y : INTEGER; keysum: SET); CONST MargGravity = 3; VAR keys: SET; old, rx: LONGINT; i, x1, dw, dh, dx, w, w0: INTEGER; changed, new: BOOLEAN; BEGIN IF (middleKey IN keysum) & F.showsParcs THEN changed := FALSE; x1 := x0 + SHORT(P.left DIV unit); (* left end of separation line *) w := SHORT(P.width DIV unit); (* width of separation line *) w0 := SHORT((P.W - P.left) DIV unit); (* width of visible part of separation line *) dh := y - y0; dw := x - x1; Oberon.RemoveMarks(x0, y0, SHORT(P.W DIV unit), SHORT(P.H DIV unit)); IF (dh <= SepH) & (dw >= -MargGravity) & (dw <= MargW+MargGravity) THEN (* left margin handle *) old := P.left; rx := P.left + LONG(w0)*unit(*P.width*) - 10*mm; REPEAT TrackMouse(x, y, keys, keysum); MoveLeft(P, rx, x0, y0, (x - x0) - dw) UNTIL keys = {}; IF keysum = {middleKey} THEN DEC(P.width, P.left - old); changed := TRUE ELSE FlipLeft(P, x0, y0); P.left := old; FlipLeft(P, x0, y0); END ELSIF (dh <= SepH) & (dw >= w-MargW-MargGravity) & (dw <= w+MargGravity) THEN (* right margin handle *) old := P.width; rx := LONG(F.W - F.left - F.right) * unit; dx := dw - SHORT(P.width DIV unit); REPEAT TrackMouse(x, y, keys, keysum); MoveRight(P, rx, x0, y0, (x - x0) - dx) UNTIL keys = {}; IF keysum = {middleKey} THEN changed := TRUE ELSE FlipRight(P, x0, y0); P.width := old; FlipRight(P, x0, y0); END; ELSIF (dw >= 0) & (dh <= SepH) THEN (* below separation line *) IF dw > 0 THEN changed := TRUE; GrabTab(P, x1, y0, x - x1, i, new); old := P.tab[i]; (*rx := P.width - MinTabDelta (*LONG(F.W - F.left - F.right) * unit - P.left*) ;*) rx := P.left + LONG(w0)*unit - MinTabDelta; REPEAT TrackMouse(x, y, keys, keysum); MoveTab(P, rx, i, x1, y0, (x - x1)) UNTIL keys = {}; IF keysum = {middleKey} THEN FlipTab(P, i, x1, y0) ELSIF keysum = {middleKey, rightKey} THEN FlipTab(P, i, x1, y0); rx := P.tab[i] - old; WHILE i < P.nofTabs-1 DO INC(i); INC(P.tab[i], rx) END ELSIF new OR (keysum = {middleKey, leftKey}) THEN RemoveTab(P, i) ELSE changed := FALSE; FlipTab(P, i, x1, y0); P.tab[i] := old; FlipTab(P, i, x1, y0) END END ELSIF dh > SepH THEN (* above separation line *) IF (P.first DIV unit <= dw) & (dw < P.first DIV unit + 5) THEN (* first mark *) old := P.first; REPEAT TrackMouse(x, y, keys, keysum); MoveFirst(P, x0, y0, (x - x1) - 4) UNTIL keys = {}; IF keysum # cancel THEN changed := TRUE; ELSE FlipFirst(P, x0, y0); P.first := old; FlipFirst(P, x0, y0); END; ELSE (* toggle adjust marks *) IF dw < w0 DIV 2 THEN Display.ReplConst(white, x1, y0+SepH+1, w0 DIV 2, 4, invert) ELSE Display.ReplConst(white, x1 + w0 DIV 2, y0+SepH+1, w0 DIV 2, 4, invert) END; REPEAT TrackMouse(x, y, keys, keysum) UNTIL keys = {}; IF dw < w0 DIV 2 THEN Display.ReplConst(white, x1, y0+SepH+1, w0 DIV 2, 4, invert) ELSE Display.ReplConst(white, x1 + w0 DIV 2, y0+SepH+1, w0 DIV 2, 4, invert) END; IF keysum = {middleKey} THEN IF dw < w0 DIV 2 THEN P.opts := P.opts / {leftAdj}; changed := TRUE; ELSE P.opts := P.opts / {rightAdj}; changed := TRUE; END END END END; IF P.left + P.first < 0 THEN P.first := -P.left; changed := TRUE ELSIF P.first > P.width-MinTabDelta THEN P.first := P.width-MinTabDelta; changed := TRUE END; IF changed THEN ChangedParc(P, pos) END END END Edit; PROCEDURE SetAttr* (P: TextFrames.Parc; F: TextFrames.Frame; pos: LONGINT; VAR S: Texts.Scanner; log: Texts.Text); VAR fnt: Fonts.Font; def, pt, lsp, dsr, new: LONGINT; changed: BOOLEAN; PROCEDURE SetMeasure (new: LONGINT; VAR old: LONGINT); BEGIN IF new # old THEN old := new; ChangedParc(P, pos) END END SetMeasure; PROCEDURE SetOpts (opts: SET); BEGIN IF P.opts #opts THEN P.opts := opts; ChangedParc(P, pos) END END SetOpts; PROCEDURE Err (s: ARRAY OF CHAR; n: INTEGER); BEGIN Str("Set "); Str(s); Str(" failed (bad "); CASE n OF 0: Str("number)") | 1: Str("indentation)") | 2: Str("option)") | 3: Str("selector)") END; Ln; END Err; BEGIN changed := FALSE; IF Matches(S, "LEAD") THEN def := TextFrames.defParc.lead DIV Scale; GetNextInt(S, new, 0, 10000, def); IF S.class = Texts.Int THEN SetMeasure(new, P.lead) ELSIF S.class = Texts.Name THEN fnt := Fonts.This(S.s); lsp := Max(fnt.height, fnt.maxY - fnt.minY) * unit; INC(lsp, (-lsp) MOD Scale); SetMeasure(lsp, P.lead) ELSE Err("lead", 0) END ELSIF Matches(S, "LINE") THEN def := TextFrames.defParc.lsp DIV Scale; GetNextInt(S, new, 10,10000, def); IF S.class = Texts.Int THEN lsp := new; dsr := lsp DIV 4; INC(dsr, (-dsr) MOD Scale) ELSIF S.class = Texts.Name THEN fnt := Fonts.This(S.s); lsp := Max(fnt.height, fnt.maxY - fnt.minY) * unit; INC(lsp, (-lsp) MOD Scale); dsr := LONG(-fnt.minY) * unit; INC(dsr, (-dsr) MOD Scale) ELSE Err("line", 0); lsp := P.lsp; dsr := P.dsr END; IF (P.lsp # lsp) OR (P.dsr # dsr) THEN P.lsp := lsp; P.dsr := dsr; changed := TRUE END ELSIF Matches(S, "FIRST") THEN def := TextFrames.defParc.first DIV Scale; GetNextInt(S, new, -10000, 10000, def); IF S.class = Texts.Int THEN IF (0 <= P.left + new) & (new <= P.width-MinTabDelta) THEN SetMeasure(new, P.first) ELSE Err("first", 1) END ELSE Err("first", 0) END ELSIF Matches(S, "LEFT") THEN def := TextFrames.defParc.left DIV Scale; GetNextInt(S, new, 0, 10000, def); IF S.class = Texts.Int THEN IF (0 <= new) & (new <= P.left + P.width - 10*mm) THEN IF new # P.left THEN INC(P.width, P.left - new); P.left := new; IF P.left + P.first < 0 THEN P.first := -P.left END; changed := TRUE; END; ELSE Err("left", 0) END ELSE Err("left", 0) END ELSIF Matches(S, "RIGHT") THEN def := (TextFrames.defParc.left + TextFrames.defParc.width) DIV Scale; GetNextInt(S, new, 0, 10000, def); IF S.class = Texts.Int THEN IF P.left + 10*mm <= new THEN IF new - P.left # P.width THEN P.width := new - P.left; IF P.first > P.width-MinTabDelta THEN P.first := P.width-MinTabDelta END; changed := TRUE; END ELSE Err("right", 0) END ELSE Err("right", 0) END ELSIF Matches(S, "WIDTH") THEN def := TextFrames.defParc.width DIV Scale; GetNextInt(S, new, 100, 10000, def); IF S.class = Texts.Int THEN IF new # P.width THEN P.width := new; IF P.first > P.width-MinTabDelta THEN P.first := P.width-MinTabDelta END; changed := TRUE; END ELSE Err("width", 0) END ELSIF Matches(S, "GRID") THEN Texts.Scan(S); IF Matches(S, "ON") THEN SetOpts(P.opts + {gridAdj}) ELSIF Matches(S, "OFF") THEN SetOpts(P.opts - {gridAdj}) ELSE Err("grid", 2) END ELSIF Matches(S, "ADJUST") THEN Texts.Scan(S); IF Matches(S, "LEFT") THEN SetOpts(P.opts - AdjMask + {leftAdj}) ELSIF Matches(S, "RIGHT") THEN SetOpts(P.opts - AdjMask + {rightAdj}) ELSIF Matches(S, "CENTER") THEN SetOpts(P.opts - AdjMask) ELSIF Matches(S, "BLOCK") THEN SetOpts(P.opts + AdjMask) ELSE Err("adjust", 2) END ELSIF Matches(S, "BREAK") THEN Texts.Scan(S); IF Matches(S, "BEFORE") THEN SetOpts(P.opts + {pageBreak}) ELSIF Matches(S, "NORMAL") THEN SetOpts(P.opts - {pageBreak}) ELSE Err("break", 2) END ELSIF Matches(S, "COLUMNS") THEN GetNextInt(S, new, 1, 3, 1); IF S.class = Texts.Int THEN IF S.i = 1 THEN IF twoColumns IN P.opts THEN P.opts := P.opts - {twoColumns}; P.width := P.width * 2 + ColumnGap; ChangedParc(P, pos) END ELSE IF ~(twoColumns IN P.opts) THEN P.opts := P.opts + {twoColumns}; P.width := (P.width - ColumnGap) DIV 2; ChangedParc(P, pos) END END ELSE Err("left", 0) END ELSIF Matches(S, "TABS") THEN IF P.nofTabs # 0 THEN changed := TRUE END; Texts.Scan(S); P.nofTabs := 0; pt := 0; IF (S.class = Texts.Char) & (S.c = "*") THEN Texts.Scan(S); IF (S.class = Texts.Int) & (S.i * Scale >= MinTabDelta) THEN changed := TRUE; WHILE (P.nofTabs < TextFrames.MaxTabs) & (pt < 3000) DO INC(pt, S.i); P.tab[P.nofTabs] := pt * Scale; INC(P.nofTabs) END END ELSE WHILE (S.class = Texts.Int) & (S.i * Scale >= pt * Scale + MinTabDelta) & (P.nofTabs < TextFrames.MaxTabs) DO changed := TRUE; pt := S.i; P.tab[P.nofTabs] := pt * Scale; INC(P.nofTabs); Texts.Scan(S) END END; ELSE Str(S.s); Int(S.i); Err("", 3); END; IF changed THEN ChangedParc(P, pos) END; IF W.buf.len # 0 THEN Texts.Append(log, W.buf) END; END SetAttr; PROCEDURE GetAttr* (P: TextFrames.Parc; F: TextFrames.Frame; VAR S: Texts.Scanner; log: Texts.Text); VAR n: INTEGER; PROCEDURE Out (n: INTEGER); VAR i: INTEGER; d: LONGINT; BEGIN CASE n OF 0: Str("lead"); Int(P.lead DIV Scale) | 1: Str("line"); Int(P.lsp DIV Scale) | 2: Str("left"); Int(P.left DIV Scale) | 3: Str("first"); Int(P.first DIV Scale) | 4: Str("width"); Int(P.width DIV Scale) | 5: Str("right"); Int((P.left + P.width) DIV Scale) | 6: IF gridAdj IN P.opts THEN Str("grid on") ELSE Str("grid off") END | 7: IF leftAdj IN P.opts THEN IF rightAdj IN P.opts THEN Str("adjust block") ELSE Str("adjust left") END ELSIF rightAdj IN P.opts THEN Str("adjust right") ELSE Str("adjust center") END | 8: IF pageBreak IN P.opts THEN Str("break before") ELSE Str("break normal") END | 9: IF twoColumns IN P.opts THEN Str("columns 2") ELSE Str("columns 1") END | 10: Str("tabs"); i := 0; IF P.nofTabs > 0 THEN d := P.tab[0]; i := 1; WHILE (i < P.nofTabs) & (P.tab[i] - P.tab[i - 1] = d) DO INC(i) END END; IF (P.nofTabs > 1) & (i = P.nofTabs) & (P.tab[i - 1] + MinTabDelta > P.width) THEN Str(" *"); Int(d DIV Scale) ELSE i := 0; WHILE i < P.nofTabs DO Int(P.tab[i] DIV Scale); INC(i) END; Str(" ~") END END END Out; BEGIN IF S.class # Texts.Name THEN Out(0); n := 1; REPEAT Ln; Out(n); INC(n) UNTIL n = 11; Ln; ELSIF Matches(S, "LEAD") THEN Out(0) ELSIF Matches(S, "LINE") THEN Out(1) ELSIF Matches(S, "LEFT") THEN Out(2) ELSIF Matches(S, "FIRST") THEN Out(3) ELSIF Matches(S, "WIDTH") THEN Out(4) ELSIF Matches(S, "RIGHT") THEN Out(5) ELSIF Matches(S, "GRID") THEN Out(6) ELSIF Matches(S, "ADJUST") THEN Out(7) ELSIF Matches(S, "BREAK") THEN Out(8) ELSIF Matches(S, "COLUMNS") THEN Out(9) ELSIF Matches(S, "TABS") THEN Out(10) ELSE Str("failed (bad selector)") END; Texts.Append(log, W.buf) END GetAttr; PROCEDURE Handle* (E: Texts.Elem; VAR msg: Texts.ElemMsg); VAR e: TextFrames.Parc; BEGIN WITH E: TextFrames.Parc DO IF msg IS TextFrames.DisplayMsg THEN WITH msg: TextFrames.DisplayMsg DO IF msg.prepare THEN Prepare(E, msg.indent, unit) ELSE Draw(E, msg.frame, msg.col, msg.X0, msg.Y0) END END ELSIF msg IS TextPrinter.PrintMsg THEN WITH msg: TextPrinter.PrintMsg DO IF msg.prepare THEN Prepare(E, msg.indent, Unit) END END ELSIF msg IS Texts.CopyMsg THEN NEW(e); CopyParc(E, e); msg(Texts.CopyMsg).e := e ELSIF msg IS TextFrames.TrackMsg THEN WITH msg: TextFrames.TrackMsg DO Edit(E, msg.frame(TextFrames.Frame), msg.pos, msg.X0, msg.Y0, msg.X, msg.Y, msg.keys) END ELSIF msg IS Texts.IdentifyMsg THEN WITH msg: Texts.IdentifyMsg DO msg.mod := "ParcElems"; msg.proc := "Alloc" END ELSIF msg IS Texts.FileMsg THEN WITH msg: Texts.FileMsg DO IF msg.id = Texts.load THEN LoadParc(E, msg.r) ELSIF msg.id = Texts.store THEN StoreParc(E, msg.r) END END ELSIF msg IS StateMsg THEN WITH msg: StateMsg DO IF msg.id = set THEN SetAttr(E, msg.frame, msg.pos, msg.par, msg.log) ELSIF msg.id = get THEN GetAttr(E, msg.frame, msg.par, msg.log) END END END END END Handle; PROCEDURE Alloc*; VAR e: TextFrames.Parc; BEGIN NEW(e); e.handle := Handle; Texts.new := e END Alloc; PROCEDURE InitDefParc (VAR def: TextFrames.Parc); VAR (*w,*) h, lsp, dsr: LONGINT; i: INTEGER; BEGIN lsp := Max(Fonts.Default.height, Fonts.Default.maxY - Fonts.Default.minY) * unit; dsr := LONG(-Fonts.Default.minY) * unit; NEW(def); def.W := 99; def.H := ParcHeight; def.handle := Handle; def.first := 0; def.left := 0; (*def.width := 165*mm;*) (*w := ((Display.Width DIV 8 * 5) - TextFrames.left - TextFrames.right - 2) * LONG(unit);*) def.width := 165*mm; (*Max(165*mm, w);*) def.lead := 0; def.lsp := lsp + (-lsp) MOD Scale; def.dsr := dsr + (-dsr) MOD Scale; def.opts := {leftAdj}; def.nofTabs := 0 END InitDefParc; PROCEDURE InitPatterns; BEGIN TabMarkImage[1] := {0..4}; TabMarkImage[2] := {0..3}; TabMarkImage[3] := {0..2}; TabMarkImage[4] := {0, 1}; TabMarkImage[5] := {0}; TabPat := Display.NewPattern(TabMarkImage, 32, 5); END InitPatterns; BEGIN Texts.OpenWriter(W); InitDefParc(TextFrames.defParc); InitPatterns; white := Display.white END ParcElems.