-- Compiler Text/nb
-- Tiberi + Stone February 7, 1980 5:46 PM
-- Tiberi January 29, 1980 2:58 PM
-- implementing module for Griffin text
-- Stone December 28, 1983 5:52 pm
-- Last Edited by: Pier, February 13, 1984 5:57:48 pm PST
DIRECTORY StyleDefs: FROM "StyleDefs" USING [StyleHandle, Anchor, Orientation],
ControllerDefs: FROM "ControllerDefs" USING [CurrentStyle, FontWithNumber],
ObjectDefs: FROM "ObjectDefs",
Rope USING [ROPE, Cat, Length, Substr, Fetch, FromChar],
Graphics USING [Context],
IO USING [BS, DEL, ESC, CR, PutFR, rope, int],
PointDefs: FROM "PointDefs"
USING [ScrPt, ObjPt, X, Y, ScrToObj, ObjToScr, ObjPtSequence],
MenuDefs: FROM "MenuDefs",
CaretDefs: FROM "CaretDefs",
RefreshDefs: FROM "RefreshDefs",
GriffinDefs: FROM "GriffinDefs" USING [UserMessage],
ScreenDefs: FROM "ScreenDefs" USING [EraseBox],
GriffinFontDefs: FROM "GriffinFontDefs";
GriffinText: PROGRAM
IMPORTS ObjectDefs, ScreenDefs, IO,
ControllerDefs, Rope, MenuDefs, PointDefs, GriffinDefs,
GriffinFontDefs, CaretDefs, RefreshDefs
EXPORTS GriffinDefs, ObjectDefs =
BEGIN
ROPE: TYPE = Rope.ROPE;
X: INTEGER = PointDefs.X;
Y: INTEGER = PointDefs.Y;
BW: CHARACTER = 27C;
typing: BOOLEAN ← FALSE;
textAnchorPt: PointDefs.ObjPt;
tl, br, tlMin, brMax: PointDefs.ObjPt;
textFont: GriffinFontDefs.FontDescriptorHandle;
textReason: {menu, newCaption, oldCaption} ← newCaption;
textString: ROPE;
textStyle: StyleDefs.StyleHandle ← NIL;
textItem: MenuDefs.MenuItemHandle ← NIL;
itemWasSelected: BOOLEAN;
textCaption: REF ObjectDefs.Object[caption] ← NIL;
StartTypeIn: PROCEDURE [pt: PointDefs.ObjPt, style: StyleDefs.StyleHandle, string: ROPE] =
BEGIN
height, width: REAL;
textAnchorPt ← pt;
textStyle ← style;
textFont ← ControllerDefs.FontWithNumber[style.fontid];
textString ← NIL;
IF string # NIL THEN textString ← Rope.Cat[textString, string];
height ← GriffinFontDefs.StringHeight[textString, textFont, style.orientation];
width ← GriffinFontDefs.StringWidth[textString, textFont, style.orientation];
tl ← tlMin ← GriffinFontDefs.TopLeft[pt,height, width, style.anchor, style.orientation,textFont.rotation];
br ← brMax ← [tl[X]+width, tl[Y]-height];
SetCaretPt;
typing ← TRUE;
END;
TypeIntoMenuItem: PUBLIC MenuDefs.MenuProc =
BEGIN OPEN MenuDefs;
itemWasSelected ← IsSelected[item];
Deselect[item];
StartTypeIn[PointDefs.ScrToObj[MenuAnchorPoint[item]], MenuStyle[], MenuString[item]];
textItem ← item;
textReason ← menu;
END;
TypeIntoCaption: PUBLIC PROCEDURE[caption: ObjectDefs.ObjectHandle] =
BEGIN OPEN ControllerDefs;
cap: REF ObjectDefs.Object[caption] ← NARROW[caption];
IF caption.style # CurrentStyle[] THEN BEGIN
ObjectDefs.EraseObject[caption];
caption.style ← CurrentStyle[];
DisplayCaption[cap, NIL];
END;
StartTypeIn[cap.p0, cap.style, cap.text];
textCaption ← cap;
textReason ← oldCaption;
END;
TypeInAtControlPt: PUBLIC PROCEDURE =
BEGIN OPEN GriffinDefs;
cps: PointDefs.ObjPtSequence ← ObjectDefs.ReadCPs[];
IF cps=NIL OR cps.length # 1 THEN SIGNAL GriffinDefs.UserMessage
["Place exactly one control point for caption."];
StartTypeIn[cps[0], ControllerDefs.CurrentStyle[], NIL];
RefreshDefs.EraseAndSaveAllCPs;
ObjectDefs.DeleteAllCPs[];
RefreshDefs.RestoreScreen;
textReason ← newCaption;
END;
TypeIn: PUBLIC PROCEDURE [ch: CHARACTER] =
BEGIN
SetBB: PROCEDURE =
BEGIN
height: REAL ← GriffinFontDefs.StringHeight[textString, textFont, textStyle.orientation];
width: REAL ← GriffinFontDefs.StringWidth[textString, textFont, textStyle.orientation];
tl ← GriffinFontDefs.TopLeft[textAnchorPt, height, width, textStyle.anchor, textStyle.orientation, textFont.rotation];
br ← [tl[X]+width, tl[Y]-height];
IF tl[X]<tlMin[X] OR tl[Y]>tlMin[Y] THEN tlMin ← tl;
IF br[X]>brMax[X] OR br[Y]<brMax[Y] THEN brMax ← br;
END;
Erase: PROCEDURE =
BEGIN ScreenDefs.EraseBox [PointDefs.ObjToScr[tlMin], PointDefs.ObjToScr[brMax], NIL] END;
DisplayString: PROCEDURE =
BEGIN
GriffinFontDefs.DisplayString[textString,
textAnchorPt, textStyle.anchor,
textStyle.orientation, textFont, NIL];
END;
IF ~typing THEN
BEGIN
TypeInAtControlPt;
END;
SELECT ch FROM
IO.ESC, IO.CR => NULL;
IO.DEL =>
BEGIN
CaretDefs.WithCaretOff[do: Erase];
textString ← NIL;
END;
IO.BS =>
BEGIN
len: INT ← Rope.Length[textString];
IF len= 0 THEN RETURN;
CaretDefs.WithCaretOff[do: Erase];
textString ← IF len=1 THEN NIL ELSE Rope.Substr[textString,0,len-1];
CaretDefs.WithCaretOff[do: DisplayString];
END;
BW =>
BEGIN
i: INTEGER;
len: INTEGER ← Rope.Length[textString];
IF len = 0 THEN RETURN;
CaretDefs.WithCaretOff[do: Erase];
FOR i DECREASING IN [0..len)
DO IF Rope.Fetch[textString,i] # ' THEN EXIT ENDLOOP;
FOR i DECREASING IN [0..i)
DO
IF Rope.Fetch[textString,i] = ' --blank-- THEN
BEGIN
textString ← Rope.Substr[textString, 0, i+1];
EXIT;
END
REPEAT FINISHED => textString ← NIL;
ENDLOOP;
CaretDefs.WithCaretOff[do: DisplayString];
END;
ENDCASE => -- normal character
BEGIN
textString ← Rope.Cat[textString,Rope.FromChar[ch]];
CaretDefs.WithCaretOff[do: Erase];
CaretDefs.WithCaretOff[do: DisplayString];
END;
SetBB;
SetCaretPt;
END;
EndTypeIn: PUBLIC PROCEDURE =
BEGIN
IF ~typing THEN RETURN;
CaretDefs.CaretOff;
SELECT textReason FROM
newCaption, oldCaption => BEGIN
IF textReason=newCaption THEN
textCaption ← NARROW[ObjectDefs.StartObject[ObjectDefs.ObjectType[caption]]];
textCaption.text ← textString;
textCaption.style ← textStyle;
textCaption.p0 ← textAnchorPt;
textCaption.validEncoding ← FALSE; --this will set the bounding box on display
IF textString=NIL
THEN []←ObjectDefs.DeleteObject[textCaption]
ELSE []←ObjectDefs.SelectObject[textCaption];
RefreshDefs.EraseAndSaveBox[PointDefs.ObjToScr[tlMin], PointDefs.ObjToScr[brMax]];
END;
menu =>
BEGIN
MenuDefs.SetMenuString[item: textItem, string: textString];
IF itemWasSelected THEN MenuDefs.Select[textItem];
RefreshDefs.EraseAndSaveBox[PointDefs.ObjToScr[tlMin], PointDefs.ObjToScr[brMax]];
END;
ENDCASE => ERROR;
typing ← FALSE;
RefreshDefs.RestoreScreen;
END;
DisplayCaption: PUBLIC PROCEDURE [cobject: REF caption ObjectDefs.Object, dc: Graphics.Context] =
BEGIN
style: StyleDefs.StyleHandle = cobject.style;
font: GriffinFontDefs.FontDescriptorHandle← ControllerDefs.FontWithNumber [style.fontid];
IF ~cobject.validEncoding THEN { --set the bounding box
ch: REAL ← GriffinFontDefs.StringHeight[cobject.text, font, style.orientation];
cw: REAL ← GriffinFontDefs.StringWidth[cobject.text, font, style.orientation];
ctl: PointDefs.ObjPt ← GriffinFontDefs.TopLeft[cobject.p0, ch, cw, style.anchor, style.orientation, font.rotation];
cbr: PointDefs.ObjPt ← [ctl[X]+cw, ctl[Y]-ch];
cobject.tl ← PointDefs.ObjToScr[ctl];
cobject.br ← PointDefs.ObjToScr[cbr];
cobject.validEncoding ← TRUE;
};
ScreenDefs.EraseBox[cobject.tl,cobject.br,dc];
GriffinFontDefs.DisplayString [cobject.text, cobject.p0, style.anchor, style.orientation, font, dc]
END;
SetCaretPt: PROCEDURE =
BEGIN
pt: PointDefs.ObjPt ← NextTL[GriffinFontDefs.MaxWidth[textFont], GriffinFontDefs.MaxHeight[textFont]];
pt[Y] ← pt[Y]-GriffinFontDefs.MaxPosExtent[textFont];
CaretDefs.CaretAt[PointDefs.ObjToScr[pt]];
END;
NextTL: PROCEDURE[width, height: REAL] RETURNS [pt: PointDefs.ObjPt] =
BEGIN
SELECT textStyle.orientation FROM
or0 => pt ← [br[X]+32, tl[Y]]; --approx 32 micas/point
or90=> pt ← [tl[X], tl[Y]-height];
or180=> pt ← [tl[X]-width, tl[Y]];
or270=> pt ← [tl[X], br[Y]+32];
ENDCASE;
END;
AppendNumber: PUBLIC PROC [rope: Rope.ROPE, number: INTEGER] RETURNS [Rope.ROPE] = {
RETURN[IO.PutFR["%s%d",IO.rope[rope],IO.int[number]]];
};
END.