home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fresh Fish 10
/
Fresh_Fish_10_2352.bin
/
new
/
dev
/
obero
/
oberon
/
demos
/
captionedit.mod
(
.txt
)
next >
Wrap
Oberon Text
|
1995-04-06
|
52KB
|
1,147 lines
Syntax10.Scn.Fnt
Syntax10i.Scn.Fnt
StampElems
Alloc
30 Jan 95
Syntax10b.Scn.Fnt
MODULE CaptionEdit; (* Copyright: ww
IMPORT
Oberon, MenuViewers, Viewers, TextFrames, Texts, Display, Fonts, Input, Modules, Files;
CONST
(* Model *)
remove* = 10; insert* = 11; move* = 12; tofront* = 13;
VersionName = "CaptionEdit (ww 15 Nov 94)";
(* Frames *)
ML = 2; MM = 1; MR = 0; Space = 5;
NoFocus* = 0; PointFocus* = 1; CaretFocus* = 2;
(* Editor *)
Menu = "System.Close System.Copy System.Grow CaptionEdit.Store ";
TYPE
(* Model *)
Panel* = POINTER TO PanelDesc;
Caption* = POINTER TO CaptionDesc;
Notifier* = PROCEDURE (panel: Panel; caption: Caption; op, beg, end: LONGINT);
CaptionDesc* = RECORD(Texts.TextDesc)
host*: Panel;
next*: Caption;
x*, y*: LONGINT;
inserted: BOOLEAN
END;
PanelDesc* = RECORD
first*: Caption;
notify*: Notifier
END;
(* Frames *)
CapInfo = POINTER TO CapInfoDesc;
CapInfoDesc = RECORD
next: CapInfo;
text: Caption;
x, y, w, h, baseH: INTEGER;
ok, marked: BOOLEAN
END;
Location* = RECORD
cap*: Caption;
pos*: LONGINT;
x*, y*: INTEGER
END;
Frame* = POINTER TO FrameDesc;
FrameDesc* = RECORD(Display.FrameDesc)
panel*: Panel;
x0*, y0*: LONGINT;
hasSel*: BOOLEAN;
selTime*: LONGINT;
selBeg*, selEnd*: Location;
focus*: INTEGER;
focusPos*: Location;
subFocus*: Display.Frame;
grid*: LONGINT;
info: CapInfo
END;
UpdateMsg* = RECORD(Display.FrameMsg)
panel*: Panel;
cap*: Caption;
op*, beg*, end*: LONGINT
END;
w, wattr: Texts.Writer;
framePat: Display.Pattern;
PROCEDURE ASSERT(b: BOOLEAN);
BEGIN IF ~b THEN HALT(99) END
END ASSERT;
(* Model *)
PROCEDURE Insert*(host: Panel; cap: Caption; x, y: LONGINT);
VAR q: Caption;
BEGIN ASSERT(~cap.inserted);
q := host.first;
IF q # NIL THEN
WHILE q.next # NIL DO q := q.next END;
q.next := cap
ELSE host.first := cap
END;
cap.next := NIL; cap.inserted := TRUE; cap.host := host; cap.x := x; cap.y := y;
host.notify(host, cap, insert, 0, 0)
END Insert;
PROCEDURE Remove*(cap: Caption);
VAR q: Caption; host: Panel;
BEGIN
IF cap.inserted THEN host := cap.host; q := host.first;
IF q # cap THEN
WHILE q.next # cap DO q := q.next END;
q.next := cap.next
ELSE host.first := cap.next
END;
cap.inserted := FALSE;
host.notify(host, cap, remove, 0, 0)
END
END Remove;
PROCEDURE Move*(cap: Caption; x, y: LONGINT);
VAR host: Panel;
BEGIN cap.x := x; cap.y := y; host := cap.host; host.notify(host, cap, move, 0, 0)
END Move;
PROCEDURE BringToFront*(cap: Caption);
VAR q: Caption; host: Panel;
BEGIN
IF cap.inserted & (cap.next # NIL) THEN host := cap.host; q := host.first;
IF q # cap THEN
WHILE q.next # cap DO q := q.next END;
q.next := cap.next
ELSE host.first := cap.next
END;
WHILE q.next # NIL DO q := q.next END;
q.next := cap; cap.next := NIL;
host.notify(host, cap, tofront, 0, 0)
END
END BringToFront;
PROCEDURE NotifyPanel*(t: Texts.Text; op: INTEGER; beg, end: LONGINT);
VAR c: Caption; p: Panel;
BEGIN c := t(Caption); p := c.host;
IF c.inserted THEN
IF (op = Texts.delete) & (c.len = 0) THEN Remove(c)
ELSE p.notify(p, c, op, beg, end)
END
ELSIF (p # NIL) & (op = Texts.insert) THEN Insert(p, c, c.x, c.y)
END
END NotifyPanel;
PROCEDURE OpenCaption*(cap: Caption; text: Texts.Text; beg, end: LONGINT);
VAR buf: Texts.Buffer;
BEGIN Texts.Open(cap, ""); cap.notify := NotifyPanel; cap.inserted := FALSE;
IF (text # NIL) & (beg < end) THEN
NEW(buf); Texts.OpenBuf(buf); Texts.Save(text, beg, end, buf); Texts.Append(cap, buf)
END
END OpenCaption;
PROCEDURE OpenPanel*(p: Panel; notifier: Notifier);
BEGIN p.first := NIL; p.notify := notifier
END OpenPanel;
PROCEDURE LoadPanel*(VAR r: Files.Rider; p: Panel);
VAR i: LONGINT; c, prev, anchor: Caption;
BEGIN OpenPanel(p, p.notify); NEW(anchor); prev := anchor; Files.ReadLInt(r, i);
WHILE i # 0 DO NEW(c); OpenCaption(c, NIL, 0, 0); prev.next := c; prev := c; c.host := p; c.inserted := TRUE;
Files.ReadLInt(r, c.x); Files.ReadLInt(r, c.y); Texts.Load(r, c);
DEC(i)
END;
p.first := anchor.next
END LoadPanel;
PROCEDURE ThisPanel*(f: Files.File; notifier: Notifier): Panel;
VAR ch: CHAR; p: Panel; r:Files.Rider;
BEGIN NEW(p); OpenPanel(p, notifier);
IF f # NIL THEN Files.Set(r, f, 0); Files.Read(r, ch);
IF ch = 0F7X THEN Files.Read(r, ch);
IF ch = 1X THEN LoadPanel(r, p) END
END
END;
RETURN p
END ThisPanel;
PROCEDURE StorePanel*(VAR r: Files.Rider; p: Panel);
VAR i: LONGINT; c: Caption;
BEGIN i := 0; c := p.first;
WHILE c # NIL DO INC(i); c := c.next END;
Files.WriteLInt(r, i); c := p.first;
WHILE c # NIL DO Files.WriteLInt(r, c.x); Files.WriteLInt(r, c.y); Texts.Store(r, c); c := c.next END
END StorePanel;
PROCEDURE File*(p: Panel; name: ARRAY OF CHAR): Files.File;
VAR f: Files.File; r: Files.Rider;
BEGIN f := Files.New(name);
Files.Set(r, f, 0); Files.Write(r, 0F7X); Files.Write(r, 1X); StorePanel(r, p);
RETURN f
END File;
(* Frames *)
(* Measurement *)
PROCEDURE MeasureChar(VAR r: Texts.Reader; ch: CHAR; VAR w, minY, maxY: INTEGER);
VAR chX, chY, chW, chH, voff: INTEGER; pat: Display.Pattern; msg: TextFrames.DisplayMsg;
BEGIN voff := r.fnt.height * r.voff DIV 64;
IF r.elem # NIL THEN msg.prepare := TRUE; msg.fnt := r.fnt; msg.col := r.col;
msg.pos := Texts.Pos(r) - 1; msg.indent := 0; msg.Y0 := r.fnt.minY;
r.elem.handle(r.elem, msg);
IF r.elem IS TextFrames.Parc THEN r.elem.W := 0; r.elem.H := 0; msg.Y0 := 0 END;
w := SHORT(r.elem.W DIV TextFrames.Unit);
minY := voff + msg.Y0; maxY := SHORT(r.elem.H DIV TextFrames.Unit) + minY
ELSE Display.GetChar(r.fnt.raster, ch, w, chX, chY, chW, chH, pat);
minY := r.fnt.minY + voff; maxY := r.fnt.maxY + voff
END
END MeasureChar;
PROCEDURE GetBoundingBox(t: Texts.Text; beg, end: LONGINT; VAR w, h, baseH: INTEGER);
VAR pos: LONGINT; minY, maxY, w1, minY1, maxY1: INTEGER; ch: CHAR; r: Texts.Reader;
BEGIN w := 0; minY := 0; maxY := 0;
Texts.OpenReader(r, t, 0); Texts.Read(r, ch); pos := 1;
WHILE ~r.eot DO MeasureChar(r, ch, w1, minY1, maxY1);
IF minY1 < minY THEN minY := minY1 END;
IF maxY1 > maxY THEN maxY := maxY1 END;
IF (pos > beg) & (pos <= end) THEN w := w + w1 END;
Texts.Read(r, ch); INC(pos)
END;
h := maxY - minY; baseH := -minY
END GetBoundingBox;
PROCEDURE Width(t: Texts.Text; beg, end: LONGINT): INTEGER;
VAR w, h, baseH: INTEGER;
BEGIN GetBoundingBox(t, beg, end, w, h, baseH); RETURN w
END Width;
PROCEDURE Offset(t: Texts.Text; dX: INTEGER): LONGINT;
VAR i: LONGINT; w, minY, maxY: INTEGER; ch: CHAR; r: Texts.Reader;
BEGIN i := 0; Texts.OpenReader(r, t, 0);
WHILE (i < t.len) & (dX > 0) DO Texts.Read(r, ch); INC(i);
MeasureChar(r, ch, w, minY, maxY); dX := dX - w
END;
IF (dX < 0) & (i # 0) THEN DEC(i) END;
RETURN i
END Offset;
(* Caption_Info *)
PROCEDURE NewInfo(f: Frame; cap: Caption; w, h, baseH: INTEGER): CapInfo;
VAR info: CapInfo;
BEGIN NEW(info); info.text := cap; info.x := SHORT(cap.x - f.x0); info.y := SHORT(cap.y - f.y0);
info.w := w; info.h := h; info.baseH := baseH;
info.ok := FALSE; info.marked := FALSE;
RETURN info
END NewInfo;
PROCEDURE ThisCaption(f: Frame; x, y: INTEGER): CapInfo;
VAR c, this: CapInfo;
BEGIN x := x - f.X; y := y - (f.Y + f.H);
c := f.info; this := NIL;
WHILE c # NIL DO
IF (c.x <= x) & (x < c.x + c.w) & (c.y <= y) & (y < c.y + c.h) THEN this := c END;
c := c.next
END;
RETURN this
END ThisCaption;
PROCEDURE SetReader(f: Frame; x, y: INTEGER; VAR r: Texts.Reader; VAR cap: CapInfo);
VAR t: Caption;
BEGIN cap := ThisCaption(f, x, y);
IF cap # NIL THEN t := cap.text; Texts.OpenReader(r, t, Offset(t, x - f.X - cap.x)) END
END SetReader;
PROCEDURE InfoAbout(f: Frame; cap: Caption): CapInfo;
VAR c: CapInfo;
BEGIN c := f.info;
WHILE (c # NIL) & (c.text # cap) DO c := c.next END;
RETURN c
END InfoAbout;
PROCEDURE InsertInfo(f: Frame; cap: CapInfo);
VAR info, p: CapInfo; q, t: Caption;
BEGIN info := f.info; p := NIL; q := f.panel.first; t := cap.text;
WHILE q # t DO
IF (info # NIL)