home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga MA Magazine 1998 #6
/
amigamamagazinepolishissue1998.iso
/
coders
/
jËzyki_programowania
/
oberon
/
system
/
parcelems.mod
(
.txt
)
< prev
next >
Wrap
Oberon Text
|
1977-12-31
|
24KB
|
545 lines
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.