-- Compiler DrawOps/n --m.stone December 2, 1981 11:24 PM --Tiberi December 11, 1979 8:42 PM DIRECTORY GriffinDefs: FROM "GriffinDefs", GriffinStartDefs: FROM "GriffinStartDefs", StringDefs: FROM "StringDefs", MenuDefs: FROM "MenuDefs", ObjectDefs: FROM "ObjectDefs", GriffinFontDefs: FROM "GriffinFontDefs", ControllerDefs: FROM "ControllerDefs", RefreshDefs: FROM "RefreshDefs", StyleDefs: FROM "StyleDefs", PointDefs: FROM "PointDefs", GriffinMemoryDefs: FROM "GriffinMemoryDefs", SplineDefs: FROM "SplineDefs", ControllerMenuDefs: FROM "ControllerMenuDefs"; DrawOps: PROGRAM IMPORTS GriffinDefs, MenuDefs, ObjectDefs, ControllerMenuDefs, StringDefs, GriffinMemoryDefs, PointDefs, ControllerDefs,RefreshDefs EXPORTS GriffinDefs, GriffinStartDefs = BEGIN OPEN ObjectDefs,PointDefs,GriffinMemoryDefs; newObj: POINTER TO shape Object ← NIL; spline: SplineDefs.SplineType ← naturalAL; Fitting: TYPE = {lines,curve}; fitting: Fitting; SetStyle: PROCEDURE[style: StyleDefs.StyleHandle] = BEGIN fd: GriffinFontDefs.FontDescriptor; name: STRING ← [128]; BugItemByString[ControllerMenuDefs.colorMenu, StringOfColor[style.fillcolor]]; BugItemByString[ControllerMenuDefs.lineColorMenu, StringOfColor[style.color]]; BugItemByString[ControllerMenuDefs.colorControlMenu, SELECT TRUE FROM style.filled AND style.outlined => "Both", style.filled => "Filled", style.outlined => "Outlined", ENDCASE => ERROR]; BugItemByString[ControllerMenuDefs.textMenu, SELECT style.orientation FROM or0 => "0 d", or90 => "90 d", or180 => "180 d", or270 => "270 d", ENDCASE => ERROR]; fd ← ControllerDefs.FontWithNumber [style.fontid]; BugItemByString[ControllerMenuDefs.charMenu, SELECT fd.rotation FROM GriffinFontDefs.Rot0Degrees => "0 char d", GriffinFontDefs.Rot90Degrees => "90 char d", GriffinFontDefs.Rot180Degrees => "180 char d", GriffinFontDefs.Rot270Degrees => "270 char d", ENDCASE => ERROR]; StringDefs.AppendString[to: name, from: fd.name]; StringDefs.AppendDecimal[name, fd.points]; SELECT fd.face FROM 3 => StringDefs.AppendString[to: name, from: "BI"]; 2 => StringDefs.AppendString[to: name, from: "B"]; 1 => StringDefs.AppendString[to: name, from: "I"]; ENDCASE; BugItemByString[ControllerMenuDefs.fontMenu, name]; BugItemByString[ControllerMenuDefs.centerMenu, SELECT style.anchor FROM left => "left", center => "centered", right => "right", ENDCASE => ERROR]; BugItemByString[ControllerMenuDefs.thickMenu, SELECT ObjValToScrVal[style.width] FROM 1 => "1 pt", 2 => "2 pt", 3 => "3 pt", 4 => "4 pt", ENDCASE => ERROR]; END; BugItemByString: PROCEDURE[menu: MenuDefs.MenuHandle, string: STRING]= BEGIN OPEN MenuDefs; menuItem: MenuItemHandle ← menu.head; IsThisItem: MenuProc = BEGIN IF StringDefs.EquivalentString[MenuString[item], string] THEN menuItem ← item; END; ForAllMenuItems[menu, IsThisItem]; BugItem[menuItem] END; ExpandShape: MenuDefs.MenuProc = BEGIN OPEN ControllerMenuDefs; IF MenuDefs.IsSelected[item] THEN UnDisplayShapeMenu[] ELSE DisplayShapeMenu[]; IF MenuDefs.IsSelected[item] THEN MenuDefs.Deselect[item] ELSE MenuDefs.Select[item]; RefreshDefs.RestoreScreen; END; ExpandColor: MenuDefs.MenuProc = BEGIN OPEN ControllerMenuDefs; IF MenuDefs.IsSelected[item] THEN UnDisplayColorMenu[] ELSE DisplayColorMenu[]; IF MenuDefs.IsSelected[item] THEN MenuDefs.Deselect[item] ELSE MenuDefs.Select[item]; RefreshDefs.RestoreScreen; END; ExpandText: MenuDefs.MenuProc = BEGIN OPEN ControllerMenuDefs; IF MenuDefs.IsSelected[item] THEN UnDisplayCaptionMenu[] ELSE DisplayCaptionMenu[]; IF MenuDefs.IsSelected[item] THEN MenuDefs.Deselect[item] ELSE MenuDefs.Select[item]; RefreshDefs.RestoreScreen; END; ApplyStyle: MenuDefs.MenuProc = BEGIN OPEN ControllerMenuDefs; --called with a selected object ChangeObj: PROCEDURE[obj: ObjectHandle]=BEGIN --if the object doesn't get any bigger, then don't need to erase it first width: REAL ← obj.style.width; outlined: BOOLEAN ← obj.style.outlined; filled: BOOLEAN ← obj.style.filled; obj.style ← ControllerDefs.CurrentStyle[]; IF width > obj.style.width OR (outlined # obj.style.outlined) OR (filled # obj.style.filled) OR obj.objectType=caption THEN RefreshDefs.EraseAndSave[obj]; RefreshDefs.PlotAndMark[obj]; END; ForAllSelectedDo[ChangeObj]; RefreshDefs.RestoreScreen[]; END; IndicateStyle: MenuDefs.MenuProc = BEGIN style: StyleDefs.StyleHandle ← NIL; SetSelectedStyle: PROCEDURE [s: ObjectDefs.ObjectHandle] = BEGIN style ← s.style END; ObjectDefs.ForAllSelectedDo [SetSelectedStyle]; IF style#NIL THEN SetStyle[style]; END; StringOfColor: PROCEDURE[color: StyleDefs.Color] RETURNS[STRING]= BEGIN RETURN[SELECT color FROM [0,0,0] => "black", [7,255,59] => "dk brown", [7,255,118] => "brown", [0,131,217] => "tan", [234,255,79] => "maroon", [0,255,160] => "dk red", [0,255,255] => "red", [10,255,255] => "orange", [25,255,255] => "dk yellow", [40,255,255] => "yellow", [40,190,255] => "lt yellow", [71,255,59] => "dk green", [76,255,255] => "green", [71,193,255] => "lt green", [150,255,170] => "dk blue", [150,255,255] => "blue", [141,150,255] => "lt blue", [107,255,98] => "dk aqua", [107,224,255] => "aqua", [120,255,255] => "cyan", [178,255,178] => "dk purple", [170,224,255] => "purple", [170,131,255] => "violet", [200,255,255] => "magenta", [206,170,255] => "pink", [0,0,40] => "dk grey", [0,0,120] => "grey", [0,0,200] => "lt grey", [0,0,230] => "pale grey", [0,0,255] => "white", ENDCASE => "black"]; END; FittingType: MenuDefs.MenuProc = BEGIN OPEN StringDefs; string: STRING ← MenuDefs.MenuString[item]; fitting ← SELECT TRUE FROM EquivalentStrings[string,"Straight"] => lines, EquivalentStrings[string,"Curved"] => curve, ENDCASE => ERROR; MenuDefs.SelectOnly[item]; END; ExpandSplines: MenuDefs.MenuProc = BEGIN IF MenuDefs.IsSelected[item] THEN MenuDefs.HideMenu[splineMenu] ELSE MenuDefs.ShowMenu[splineMenu]; IF MenuDefs.IsSelected[item] THEN MenuDefs.Deselect[item] ELSE MenuDefs.Select[item]; RefreshDefs.RestoreScreen; END; SplineType: MenuDefs.MenuProc = BEGIN OPEN StringDefs; string: STRING ← MenuDefs.MenuString[item]; IF newObj#NIL THEN GriffinDefs.UserMessage["Only one spline type per object"]; spline ← SELECT TRUE FROM EquivalentStrings[string,"Natural: Arc Length"] => naturalAL, EquivalentStrings[string,"Natural: Unit Length"] => naturalUM, EquivalentStrings[string,"Bezier Curve"] => bezier, EquivalentStrings[string,"B-Spline"] => bspline, EquivalentStrings[string,"Catmull-Rom Curve"] => crspline, ENDCASE => ERROR; MenuDefs.SelectOnly[item]; END; SetSplineType: PROCEDURE[splinetype: SplineDefs.SplineType] = BEGIN OPEN StringDefs; string: STRING ← SELECT splinetype FROM naturalAL => "Natural: Arc Length", naturalUM => "Natural: Unit Length", bezier => "Bezier Curve", bspline => "B-Spline", crspline => "Catmull-Rom Curve", ENDCASE => ERROR; BugItemByString[splineMenu, string]; END; NewLink: MenuDefs.MenuProc = BEGIN tempLink: POINTER TO Link ← NIL; lastPt: PointDefs.ScrPt; cps: DESCRIPTOR FOR ARRAY OF PointDefs.ObjPt; IF spline=bspline OR spline=crspline THEN GriffinDefs.UserMessage["B-Splines and Catmull-Rom Curves cannot be used in linked objects"]; cps ← ReadCPs[]; IF LENGTH[cps] <=1 THEN BEGIN IF LENGTH[cps]#0 THEN Free[BASE[cps]]; RETURN; END; lastPt ← PointDefs.ObjToScr[cps[LENGTH[cps]-1]]; tempLink ← MakeLink[fitting=lines,cps]; IF newObj=NIL THEN BEGIN newObj ← LOOPHOLE[StartObject[shape]]; newObj.body ← shape[FALSE,[spline,linked[tempLink]],NIL,NIL]; newObj.style ← ControllerDefs.CurrentStyle[]; newObj.cluster ← OpenCluster; END ELSE AddLink[newObj,tempLink]; RefreshDefs.EraseAndSaveAllCPs[]; DeleteAllCPs[]; WriteLink[newObj,tempLink]; AddToken[lastPt,open]; RefreshDefs.RestoreScreen[]; END; MakeLink: PROCEDURE[isLines: BOOLEAN,cps: DESCRIPTOR FOR ARRAY OF PointDefs.ObjPt]RETURNS[newLink: POINTER TO Link] = BEGIN newLink ← Allocate[SIZE[Link]]; newLink↑ ← [NIL, (IF isLines THEN D1 ELSE D3), cps]; END; BackLink: MenuDefs.MenuProc = BEGIN lastLink: POINTER TO Link ← GetNewObjectLinks[]; RefreshDefs.EraseAndSaveAllCPs[]; DeleteAllCPs[]; --case of nil object. Shouldn't happen; IF lastLink = NIL THEN BEGIN [] ← DeleteObject[newObj]; newObj ← NIL; RefreshDefs.RestoreScreen[]; RETURN; END; --case of one link IF lastLink.link = NIL THEN BEGIN ShowKnots[lastLink.knots,FALSE]; RefreshDefs.EraseAndSave[newObj]; [] ← DeleteObject[newObj]; newObj ← NIL; RefreshDefs.RestoreScreen[]; RETURN; END; UNTIL lastLink.link=NIL DO lastLink ← lastLink.link; ENDLOOP; ShowLinkKnots[lastLink.knots,FALSE]; DeleteLink[newObj,lastLink]; --does an erase too RefreshDefs.RestoreScreen[]; END; ShowLinkKnots: PROCEDURE[knots: DESCRIPTOR FOR ARRAY OF ObjPt, exceptLast: BOOLEAN] = BEGIN i: CARDINAL; lastknot: CARDINAL ← LENGTH[knots]-1; cps: DESCRIPTOR FOR ARRAY OF PointDefs.ObjPt ← ReadCPs[]; DeleteAllCPs[]; IF exceptLast THEN lastknot ← lastknot-1; AddToken[ObjToScr[knots[0]], open]; FOR i IN [1..lastknot] DO AddToken[ObjToScr[knots[i]], CP]; ENDLOOP; IF LENGTH[cps]#0 THEN BEGIN FOR i IN [0..LENGTH[cps]) DO AddToken[ObjToScr[cps[i]], CP]; ENDLOOP; Free[BASE[cps]]; END; END; GetNewObjectLinks: PROCEDURE RETURNS [link: POINTER TO Link]= BEGIN IF newObj=NIL THEN RETURN[NIL]; WITH traj: newObj.trajectory SELECT FROM linked => link ← traj.links; ENDCASE => ERROR; RETURN; END; Draw: MenuDefs.MenuProc = BEGIN DrawObject[newObj,FALSE]; END; Close: MenuDefs.MenuProc = BEGIN DrawObject[newObj,TRUE]; END; Box: MenuDefs.MenuProc = BEGIN cps: DESCRIPTOR FOR ARRAY OF PointDefs.ObjPt; pt: ObjPt; cps ← ReadCPs[]; IF LENGTH[cps] #2 THEN SIGNAL GriffinDefs.UserMessage["Exactly 2 points for a box"]; DeleteAllCPs[]; AddToken[ObjToScr[cps[0]],CP]; pt ← [cps[0][X],cps[1][Y]]; AddToken[ObjToScr[pt],CP]; AddToken[ObjToScr[cps[1]],CP]; pt ← [cps[1][X],cps[0][Y]]; AddToken[ObjToScr[pt],CP]; Free[BASE[cps]]; BugItemByString[shapeMenu,"Straight"]; DrawObject[newObj,TRUE]; END; Modify: MenuDefs.MenuProc = BEGIN selected: ObjectHandle ← NIL; FindLastSelected: PROCEDURE[obj: ObjectHandle]=BEGIN selected ← obj; END; IF newObj#NIL THEN RETURN; --don't modify while drawing or modifying ForAllSelectedDo[FindLastSelected]; IF selected=NIL THEN RETURN; WITH obj: selected SELECT FROM shape => BEGIN SetStyle[selected.style]; SetSplineType[obj.trajectory.splineType]; DeSelectObject[selected]; --will get selected again when finished EraseObject[selected]; ShowCPs[selected]; END; caption => BEGIN token: ObjectHandle ← ReturnSelected[selected]; IF token#NIL THEN EraseObject[token]; DeSelectObject[selected]; --will get selected again when finished SetStyle[selected.style]; GriffinDefs.TypeIntoCaption[selected]; END; ENDCASE => RETURN; END; ShowCPs: PROCEDURE[object: ObjectHandle] = BEGIN obj: POINTER TO shape Object ←NIL; IF object=NIL THEN RETURN; WITH foo: object SELECT FROM shape => obj ← @foo; ENDCASE => ERROR; WITH traj: obj.trajectory SELECT FROM linked => BEGIN link: POINTER TO Link ← traj.links; IF link = NIL THEN ERROR; --object with one link IF link.link=NIL THEN BEGIN ShowKnots[link.knots,obj.closed]; IF link.degree=D1 THEN BugItemByString[shapeMenu,"Straight"] ELSE BugItemByString[shapeMenu,"Curved"]; [] ← DeleteObject[obj]; END --multiple links. Order here is important ELSE BEGIN closed: BOOLEAN ← obj.closed; newObj ← obj; newObj.closed ← FALSE; newObj.cluster ← OpenCluster; --delete last link FOR link ← traj.links , link.link UNTIL link.link=NIL DO ENDLOOP; --link is now last link in the object ShowLinkKnots[link.knots,closed]; IF link.degree=D1 THEN BugItemByString[shapeMenu,"Straight"] ELSE BugItemByString[shapeMenu,"Curved"]; DeleteLink[obj,link]; --plot the rest FOR link ← traj.links , link.link UNTIL link=NIL DO WriteLink[obj,link]; ENDLOOP; END; END; cyclic => BEGIN ShowKnots[traj.knots, FALSE]; BugItemByString[shapeMenu,"Curved"]; [] ← DeleteObject[obj]; END; ENDCASE; END; ShowKnots: PROCEDURE[knots: DESCRIPTOR FOR ARRAY OF ObjPt, exceptLast: BOOLEAN] = BEGIN i: CARDINAL; lastknot: CARDINAL ← LENGTH[knots]-1; IF exceptLast THEN lastknot ← lastknot-1; FOR i IN [0..lastknot] DO AddToken[ObjToScr[knots[i]], CP]; ENDLOOP; END; DrawObject: PROCEDURE[object: ObjectHandle, closed: BOOLEAN] = BEGIN shapeObj: POINTER TO shape Object ← NIL; cps: DESCRIPTOR FOR ARRAY OF PointDefs.ObjPt ← ReadCPs[]; IF object=NIL AND LENGTH[cps]<1 THEN BEGIN IF LENGTH[cps]#0 THEN Free[BASE[cps]]; RETURN; END; IF object = NIL THEN BEGIN object ← StartObject[shape]; object.body ← shape[closed,[spline,linked[NIL]],NIL,NIL]; object.style ← ControllerDefs.CurrentStyle[]; END; --loophole the elegant way WITH obj: object SELECT FROM shape => shapeObj ← @obj; ENDCASE; shapeObj.closed ← closed; WITH traj: shapeObj.trajectory SELECT FROM cyclic => shapeObj.trajectory ← [spline,cyclic[cps]]; linked => IF traj.links=NIL AND closed AND fitting=curve THEN shapeObj.trajectory ← [spline,cyclic[cps]] ELSE BEGIN --assume linked from here on down link: POINTER TO Link; IF closed THEN BEGIN IF traj.links=NIL THEN AddToken[ObjToScr[cps[0]],CP] ELSE AddToken[ObjToScr[traj.links.knots[0]],CP]; Free[BASE[cps]]; cps ← ReadCPs[]; shapeObj.closed ← TRUE; END; link ← MakeLink[fitting=lines,cps]; AddLink[shapeObj,link]; WriteLink[shapeObj,link]; END; ENDCASE; object.cluster ← 0; RefreshDefs.PlotAndMark[object]; [] ← ObjectDefs.SelectObject[object]; RefreshDefs.RestoreScreen[]; RefreshDefs.EraseAndSaveAllCPs[]; DeleteAllCPs[]; RefreshDefs.RestoreScreen[]; newObj ← NIL; END; editMenu: PUBLIC MenuDefs.MenuHandle←NIL; styleMenu: PUBLIC MenuDefs.MenuHandle←NIL; shapeMenu: PUBLIC MenuDefs.MenuHandle←NIL; splineMenu: PUBLIC MenuDefs.MenuHandle←NIL; default: MenuDefs.MenuItemHandle←NIL; showstyle: MenuDefs.MenuItemHandle←NIL; newLink: MenuDefs.MenuItemHandle←NIL; editMenu ← MenuDefs.CreateMenu[horizontal, [100,500], NIL]; []←MenuDefs.AddMenuItem[editMenu,"Draw",Draw]; []←MenuDefs.AddMenuItem[editMenu,"Close",Close]; []←MenuDefs.AddMenuItem[editMenu,"Draw link",NewLink]; []←MenuDefs.AddMenuItem[editMenu,"Modify",Modify]; []←MenuDefs.AddMenuItem[editMenu,"Back link",BackLink]; []←MenuDefs.AddMenuItem[editMenu,"Box",Box]; []←MenuDefs.AddMenuItem[editMenu,"Spline Type",ExpandSplines]; shapeMenu ← MenuDefs.CreateMenu[vertical, [100,550], NIL]; default ←MenuDefs.AddMenuItem[shapeMenu,"Straight",FittingType]; []←MenuDefs.AddMenuItem[shapeMenu,"Curved",FittingType]; MenuDefs.BugItem[default]; splineMenu ← MenuDefs.CreateMenu[vertical, [200,550], NIL]; default ←MenuDefs.AddMenuItem[splineMenu,"Natural: Arc Length",SplineType]; []←MenuDefs.AddMenuItem[splineMenu,"Natural: Unit Length",SplineType]; []←MenuDefs.AddMenuItem[splineMenu,"Bezier Curve",SplineType]; []←MenuDefs.AddMenuItem[splineMenu,"B-Spline",SplineType]; []←MenuDefs.AddMenuItem[splineMenu,"Catmull-Rom Curve",SplineType]; MenuDefs.BugItem[default]; styleMenu ← MenuDefs.CreateMenu[vertical, [400,200], NIL]; []←MenuDefs.AddMenuItem [styleMenu, "Indicate", IndicateStyle]; []←MenuDefs.AddMenuItem [styleMenu, "Apply", ApplyStyle]; []←MenuDefs.AddMenuItem [styleMenu, "Shape Style", ExpandShape]; []←MenuDefs.AddMenuItem [styleMenu, "Color Style", ExpandColor]; []←MenuDefs.AddMenuItem [styleMenu, "Text Style", ExpandText]; END.