-- Compiler Text/nb -- Tiberi + Stone February 7, 1980 5:46 PM -- Tiberi January 29, 1980 2:58 PM -- implementing module for Griffin text DIRECTORY StyleDefs: FROM "StyleDefs" USING [StyleHandle, Anchor, Orientation], GriffinMemoryDefs: FROM "GriffinMemoryDefs" USING [AllocateString, FreeString, Free], ControllerDefs: FROM "ControllerDefs" USING [CurrentStyle, FontWithNumber], ObjectDefs: FROM "ObjectDefs", StringDefs: FROM "StringDefs" USING [AppendString], IODefs: FROM "IODefs" USING [BS, DEL, ESC, CR], PointDefs: FROM "PointDefs" USING [ScrPt, ObjPt, X, Y, ScrToObj, ObjToScr, ObjValToScrVal], BitBltDefs: FROM "BitBltDefs" USING [BBoperation], MenuDefs: FROM "MenuDefs", CaretDefs: FROM "CaretDefs", RefreshDefs: FROM "RefreshDefs", GriffinDefs: FROM "GriffinDefs" USING [UserMessage], ScreenDefs: FROM "ScreenDefs" USING [MoveScreenBox, EraseBox, SetFunction], GriffinFontDefs: FROM "GriffinFontDefs"; Text: PROGRAM IMPORTS GriffinMemoryDefs, ObjectDefs, ScreenDefs, ControllerDefs, StringDefs, MenuDefs, PointDefs, GriffinDefs, GriffinFontDefs, CaretDefs, RefreshDefs EXPORTS GriffinDefs, ObjectDefs = BEGIN OPEN GriffinFontDefs; X: CARDINAL = PointDefs.X; Y: CARDINAL = PointDefs.Y; BW: CHARACTER = 27C; maxStringLength: CARDINAL = 200; typing: BOOLEAN ← FALSE; textAnchorPt: PointDefs.ObjPt; tlCaret, tl, br, tlMax, brMax: PointDefs.ScrPt; textFont: GriffinFontDefs.FontDescriptor; textReason: {menu, newCaption, oldCaption} ← newCaption; textString: STRING = [maxStringLength]; textStyle: StyleDefs.StyleHandle ← NIL; textItem: MenuDefs.MenuItemHandle ← NIL; itemWasSelected: BOOLEAN; textCaption: ObjectDefs.ObjectHandle ← NIL; StartTypeIn: PROCEDURE [pt: PointDefs.ScrPt, style: StyleDefs.StyleHandle, string: STRING] = BEGIN OPEN GriffinFontDefs; height, width: CARDINAL; textAnchorPt ← PointDefs.ScrToObj[pt]; textStyle ← style; textFont ← ControllerDefs.FontWithNumber[style.fontid]; textString.length ← 0; IF string # NIL THEN StringDefs.AppendString[textString, string]; height ← StringHeight[textString, @textFont, style.orientation]; width ← StringWidth[textString, @textFont, style.orientation]; tl ← tlMax ← PointDefs.ObjToScr[TopLeft[PointDefs.ScrToObj[pt], height, width, style.anchor, style.orientation, textFont.rotation]]; br ← brMax ← [tl[X]+PointDefs.ObjValToScrVal[width], tl[Y]+PointDefs.ObjValToScrVal[height]]; SetCaretPt; typing ← TRUE; END; TypeIntoMenuItem: PUBLIC MenuDefs.MenuProc = BEGIN OPEN MenuDefs; itemWasSelected ← IsSelected[item]; Deselect[item]; StartTypeIn[MenuAnchorPoint[item], MenuStyle[], MenuString[item]]; textItem ← item; textReason ← menu; END; TypeIntoCaption: PUBLIC PROCEDURE[caption: ObjectDefs.ObjectHandle] = BEGIN OPEN ControllerDefs; WITH cap: caption SELECT FROM caption => BEGIN IF caption.style # CurrentStyle[] THEN BEGIN ObjectDefs.EraseObject[caption]; caption.style ← CurrentStyle[]; DisplayCaption[@cap]; END; StartTypeIn[PointDefs.ObjToScr[cap.p0], cap.style, cap.text]; END; ENDCASE => ERROR; textCaption ← caption; textReason ← oldCaption; END; TypeInAtControlPt: PUBLIC PROCEDURE = BEGIN OPEN GriffinDefs; pt: PointDefs.ScrPt; cps: DESCRIPTOR FOR ARRAY OF PointDefs.ObjPt ← ObjectDefs.ReadCPs[]; IF LENGTH[cps] # 1 THEN SIGNAL GriffinDefs.UserMessage ["Place exactly one control point for caption."]; pt ← PointDefs.ObjToScr[cps[0]]; StartTypeIn[pt, ControllerDefs.CurrentStyle[], NIL]; RefreshDefs.EraseAndSaveAllCPs; ObjectDefs.DeleteAllCPs[]; GriffinMemoryDefs.Free[BASE[cps]]; RefreshDefs.RestoreScreen; textReason ← newCaption; END; TypeIn: PUBLIC PROCEDURE [ch: CHARACTER] = BEGIN OPEN StyleDefs; bltpt: PointDefs.ScrPt; tlOld,brOld: PointDefs.ScrPt; twiddle: CARDINAL; width: CARDINAL; height: CARDINAL; font: GriffinFontDefs.FontDescriptorHandle = @textFont; vertical, aligned: BOOLEAN; SetBB: PROCEDURE = BEGIN IF tl[X]<tlMax[X] OR tl[Y]<tlMax[Y] THEN tlMax ← tl; IF br[X]>brMax[X] OR br[Y]>brMax[Y] THEN brMax ← br; height ← StringHeight[textString, @textFont, textStyle.orientation]; width ← StringWidth[textString, @textFont, textStyle.orientation]; tl ← PointDefs.ObjToScr[TopLeft[textAnchorPt, height, width, textStyle.anchor, textStyle.orientation, textFont.rotation]]; br ← [tl[X]+PointDefs.ObjValToScrVal[width], tl[Y]+PointDefs.ObjValToScrVal[height]]; IF tl[X]<tlMax[X] OR tl[Y]<tlMax[Y] THEN tlMax ← tl; IF br[X]>brMax[X] OR br[Y]>brMax[Y] THEN brMax ← br; END; Erase: PROCEDURE = BEGIN ScreenDefs.EraseBox [tl, br] END; DisplayString: PROCEDURE = BEGIN GriffinFontDefs.DisplayString[textString, PointDefs.ObjToScr[textAnchorPt], textStyle.anchor, textStyle.orientation, @textFont]; END; IF ~typing THEN BEGIN TypeInAtControlPt; END; vertical ← textStyle.orientation = or90 OR textStyle.orientation = or270; aligned ← IF vertical THEN font.rotation = Rot0Degrees OR font.rotation = Rot180Degrees ELSE font.rotation = Rot90Degrees OR font.rotation = Rot270Degrees; SELECT ch FROM IODefs.ESC, IODefs.CR => NULL; IODefs.DEL => BEGIN CaretDefs.WithCaretOff[do: Erase]; textString.length ← 0; SetBB; SetCaretPt; RETURN; END; IODefs.BS => BEGIN IF textString.length = 0 THEN RETURN; CaretDefs.WithCaretOff[do: Erase]; textString.length ← textString.length - 1; CaretDefs.WithCaretOff[do: DisplayString]; SetBB; SetCaretPt; RETURN; END; BW => BEGIN i: CARDINAL; IF textString.length = 0 THEN RETURN; CaretDefs.WithCaretOff[do: Erase]; FOR i DECREASING IN [0..textString.length) DO IF textString[i] # ' THEN EXIT ENDLOOP; FOR i DECREASING IN [0..i) DO IF textString[i] = ' --blank-- THEN BEGIN textString.length ← i+1; EXIT; END REPEAT FINISHED => textString.length ← 0; ENDLOOP; CaretDefs.WithCaretOff[do: DisplayString]; SetBB; SetCaretPt; RETURN; END; ENDCASE => -- normal character BEGIN ShowChar: PROCEDURE = BEGIN ScreenDefs.SetFunction[replace]; GriffinFontDefs.BltChar [ch, bltpt, font] END; IF textString.length = maxStringLength THEN SIGNAL GriffinDefs.UserMessage["String too long."]; bltpt ← NextTL[Width[ch, font], Height[ch, font]]; width ← PointDefs.ObjValToScrVal[Width[ch, font]]; height ← PointDefs.ObjValToScrVal[Height[ch, font]]; twiddle ← IF vertical THEN (PointDefs.ObjValToScrVal[MaxWidth[font]] - width)/2 ELSE (PointDefs.ObjValToScrVal[MaxHeight[font]] - height)/2; IF aligned THEN IF vertical THEN bltpt[X] ← bltpt[X] + twiddle ELSE bltpt[Y] ← bltpt[Y] + twiddle; CaretDefs.WithCaretOff[do: ShowChar]; IF aligned THEN IF vertical THEN bltpt[X] ← bltpt[X] - twiddle ELSE bltpt[Y] ← bltpt[Y] - twiddle; SELECT textStyle.orientation FROM or0 => br[X] ← br[X] + width; or90 => tl[Y] ← bltpt[Y]; or180 => tl[X] ← bltpt[X]; or270 => br[Y] ← br[Y] + height; ENDCASE; textString [textString.length] ← ch; textString.length ← textString.length + 1; END; tlOld ← tl; brOld ← br; SetBB; SetCaretPt; SELECT textStyle.anchor FROM left => NULL; center, right => BEGIN Move: PROCEDURE = BEGIN ScreenDefs.MoveScreenBox [tlOld, brOld, tl[X]-tlOld[X], tl[Y]-tlOld[Y]]; END; Erase: PROCEDURE = BEGIN ScreenDefs.EraseBox[tlSlop, brSlop]; END; tlSlop, brSlop: PointDefs.ScrPt; CaretDefs.WithCaretOff[do: Move]; SELECT textStyle.orientation FROM or0 => BEGIN tlSlop ← [br[X]+1, tl[Y]]; brSlop ← brOld; END; or90 => BEGIN tlSlop ← tlOld; brSlop ← [br[X], tl[Y]-1]; END; or180 => BEGIN tlSlop ← tlOld; brSlop ← [tl[X]-1, br[Y]]; END; or270 => BEGIN tlSlop ← [tl[X], br[Y]+1]; brSlop ← brOld; END; ENDCASE; CaretDefs.WithCaretOff[do: Erase]; END; ENDCASE; END; EndTypeIn: PUBLIC PROCEDURE = BEGIN string: STRING; IF ~typing THEN RETURN; CaretDefs.CaretOff; SELECT textReason FROM newCaption => BEGIN -- put caption in object list textCaption ← ObjectDefs.StartObject[ObjectDefs.ObjectType [caption]]; textCaption.validEncoding ← TRUE; textCaption.body ← caption[p0: [0,0], text: NIL]; textReason ← oldCaption; EndTypeIn[]; --note recursion END; oldCaption => WITH cap: textCaption SELECT FROM caption => BEGIN IF cap.text # NIL THEN GriffinMemoryDefs.FreeString[cap.text]; string ← GriffinMemoryDefs.AllocateString [textString.length]; StringDefs.AppendString [string, textString]; cap.style ← textStyle; cap.body ← caption [p0: textAnchorPt, text: string]; cap.tl ← tl; cap.br ← br; IF textString.length=0 THEN []←ObjectDefs.DeleteObject[textCaption] ELSE []←ObjectDefs.SelectObject[textCaption]; RefreshDefs.EraseAndSaveBox[tlMax, brMax]; END; ENDCASE => ERROR; menu => BEGIN MenuDefs.SetMenuString[item: textItem, string: textString]; IF itemWasSelected THEN MenuDefs.Select[textItem]; RefreshDefs.EraseAndSaveBox[tlMax, brMax]; END; ENDCASE => ERROR; typing ← FALSE; RefreshDefs.RestoreScreen; END; DisplayCaption: PUBLIC PROCEDURE [cobject: POINTER TO caption ObjectDefs.Object] = BEGIN style: StyleDefs.StyleHandle = cobject.style; pt: PointDefs.ObjPt = cobject.p0; font: GriffinFontDefs.FontDescriptor ← ControllerDefs.FontWithNumber [style.fontid]; height: CARDINAL ← StringHeight[cobject.text, @font, style.orientation]; width: CARDINAL ← StringWidth[cobject.text, @font, style.orientation]; cobject.tl ← PointDefs.ObjToScr[TopLeft[pt, height, width, style.anchor, style.orientation, font.rotation]]; cobject.br ← [cobject.tl[X]+PointDefs.ObjValToScrVal[width], cobject.tl[Y]+PointDefs.ObjValToScrVal[height]]; cobject.validEncoding ← TRUE; ScreenDefs.EraseBox[cobject.tl,cobject.br]; GriffinFontDefs.DisplayString [cobject.text, PointDefs.ObjToScr[pt], style.anchor, style.orientation, @font] END; SetCaretPt: PROCEDURE = BEGIN pt: PointDefs.ScrPt; tlCaret ← NextTL[MaxWidth[@textFont], MaxHeight[@textFont]]; pt ← [tlCaret[X], tlCaret[Y]+PointDefs.ObjValToScrVal[BaseLine[@textFont]]]; CaretDefs.CaretAt[pt]; END; NextTL: PROCEDURE[width, height: CARDINAL] RETURNS [pt: PointDefs.ScrPt] = BEGIN SELECT textStyle.orientation FROM or0 => pt ← [br[X]+1, tl[Y]]; or90=> pt ← [tl[X], tl[Y]-PointDefs.ObjValToScrVal[height]]; or180=> pt ← [tl[X]-PointDefs.ObjValToScrVal[width], tl[Y]]; or270=> pt ← [tl[X], br[Y]+1]; ENDCASE; END; END.