DIRECTORY Atom, BasicTime, BiScrollers, Convert, EBMesaLisp, Feedback, FeedbackTypes, FileNames, FS, GGBasicTypes, GGCaret, GGContainer, GGControlPanelTypes, GGDescribe, GGEvent, GGFileOps, GGFont, GGHistory, GGHistoryTypes, GGInterfaceTypes, GGModelTypes, GGRefreshTypes, GGSegmentTypes, GGSessionLog, GGSliceOps, GGState, GGUIUtility, GGUserInput, GGUtility, ImagerColor, IO, MJSContainers, MultiCursors, Rope, SessionLog, SlackProcess, ViewerClasses; GGUIUtilityImpl: CEDAR PROGRAM IMPORTS Atom, BasicTime, BiScrollers, Convert, EBMesaLisp, Feedback, FileNames, FS, GGCaret, GGDescribe, GGEvent, GGFileOps, GGFont, GGSessionLog, GGSliceOps, GGState, GGUIUtility, GGUserInput, GGUtility, IO, MJSContainers, Rope, SessionLog, SlackProcess EXPORTS GGContainer, GGHistoryTypes, GGInterfaceTypes, GGSessionLog, GGUIUtility = BEGIN Change: PUBLIC TYPE = GGHistory.Change; -- exported to GGHistoryTypes ControlsObj: PUBLIC TYPE = GGControlPanelTypes.ControlsObj; -- exported to GGInterfaceTypes HistoryEvent: TYPE = GGHistoryTypes.HistoryEvent; Point: TYPE = GGBasicTypes.Point; Vector: TYPE = GGBasicTypes.Vector; AlignmentPoint: TYPE = GGInterfaceTypes.AlignmentPoint; DisplayStyle: TYPE = GGModelTypes.DisplayStyle; MsgRouter: TYPE = FeedbackTypes.MsgRouter; FeatureData: TYPE = GGModelTypes.FeatureData; FontData: TYPE = GGModelTypes.FontData; GGData: TYPE = GGInterfaceTypes.GGData; GravityType: TYPE = GGInterfaceTypes.GravityType; RefreshDataObj: PUBLIC TYPE = GGRefreshTypes.RefreshDataObj; Segment: TYPE = GGSegmentTypes.Segment; Slice: TYPE = GGModelTypes.Slice; SliceDescriptor: TYPE = GGModelTypes.SliceDescriptor; Traj: TYPE = GGModelTypes.Traj; TrajData: TYPE = GGModelTypes.TrajData; Viewer: TYPE = ViewerClasses.Viewer; UnlinkError: SIGNAL = CODE; DescribeFeature: PUBLIC PROC [feature: FeatureData, hitData: REF ANY, ggData: GGData] RETURNS [rope: Rope.ROPE] = { IF feature = NIL THEN RETURN["nothing"] ELSE { SELECT feature.type FROM slice => { slice: Slice _ NARROW[feature.shape, SliceDescriptor].slice; rope _ GGSliceOps.DescribeHit[slice, hitData]; }; distanceLine => rope _ "distance line"; slopeLine => rope _ "slope line"; angleLine => rope _ "angle line"; symmetryLine => rope _ "symmetry line"; radiiCircle => rope _ "compass circle"; intersectionPoint => { firstObj, secondObj: Rope.ROPE; alignPoint: AlignmentPoint _ NARROW[feature.shape]; line1: FeatureData _ alignPoint.curve1; line2: FeatureData _ alignPoint.curve2; tangent: BOOL _ alignPoint.tangent; IF line1 = NIL AND line2 = NIL THEN { rope _ IO.PutFR["the anchor"]; } ELSE { firstObj _ IF line1 # NIL THEN DescribeSourceFeature[line1, ggData] ELSE "unknown"; secondObj _ IF line2 # NIL THEN DescribeSourceFeature[line2, ggData] ELSE "unknown"; IF tangent THEN rope _ IO.PutFR["a %g/%g tangency point", [rope[firstObj]], [rope[secondObj]] ] ELSE rope _ IO.PutFR["a %g/%g intersection point", [rope[firstObj]], [rope[secondObj]] ]; }; }; midpoint => { alignPoint: AlignmentPoint _ NARROW[feature.shape]; curveFeature: FeatureData _ alignPoint.curve1; SELECT curveFeature.type FROM slice => { slice: Slice _ NARROW[curveFeature.shape, SliceDescriptor].slice; rope _ GGSliceOps.DescribeHit[slice, hitData]; }; ENDCASE => rope _ "unknown"; rope _ IO.PutFR["midpoint of %g", [rope[rope]]]; }; anchor => { rope _ IO.PutFR["anchor"]; }; ENDCASE => ERROR; }; }; DescribeSourceFeature: PUBLIC PROC [feature: FeatureData, ggData: GGData] RETURNS [rope: Rope.ROPE] = { IF feature = NIL THEN RETURN["nothing"] ELSE { SELECT feature.type FROM slice => rope _ Rope.Concat[Atom.GetPName[GGSliceOps.GetType[NARROW[feature.shape, SliceDescriptor].slice]], " slice"]; distanceLine => rope _ "distance line"; slopeLine => rope _ "slope line"; angleLine => rope _ "angle line"; symmetryLine => rope _ "symmetry line"; radiiCircle => rope _ "compass circle"; intersectionPoint => { firstObj, secondObj: Rope.ROPE; firstObj _ IF NARROW[feature.shape, AlignmentPoint].curve1 # NIL THEN DescribeSourceFeature[NARROW[feature.shape, AlignmentPoint].curve1, ggData] ELSE "unknown"; secondObj _ IF NARROW[feature.shape, AlignmentPoint].curve2 # NIL THEN DescribeSourceFeature[NARROW[feature.shape, AlignmentPoint].curve2, ggData] ELSE "unknown"; rope _ IO.PutFR["a %g/%g intersection point", [rope[firstObj]], [rope[secondObj]] ]; }; midpoint => rope _ IO.PutFR["midpoint of segment ???"]; ENDCASE => ERROR; }; }; GravityTypeToRope: PUBLIC PROC [gravityType: GravityType] RETURNS [rope: Rope.ROPE] = { rope _ SELECT gravityType FROM pointsPreferred => "pointsPreferred", facesPreferred => "facesPreferred", linesPreferred => "linesPreferred", ENDCASE => ERROR }; GravityTypeFromRope: PUBLIC PROC [rope: Rope.ROPE] RETURNS [gravityType: GravityType] = { gravityType _ SELECT TRUE FROM Rope.Equal[rope, "pointsPreferred", FALSE] => pointsPreferred, Rope.Equal[rope, "facesPreferred", FALSE] => facesPreferred, Rope.Equal[rope, "linesPreferred", FALSE] => linesPreferred, ENDCASE => ERROR; }; DisplayStyleToRope: PUBLIC PROC [displayStyle: DisplayStyle] RETURNS [rope: Rope.ROPE] = { rope _ IF displayStyle=screen THEN "screen" ELSE "print"; }; DisplayStyleFromRope: PUBLIC PROC [rope: Rope.ROPE] RETURNS [displayStyle: DisplayStyle] = { displayStyle _ SELECT TRUE FROM Rope.Equal[rope, "screen", FALSE] => screen, Rope.Equal[rope, "print", FALSE] => print, ENDCASE => ERROR; }; GGContainerCreate: PUBLIC PROC [info: ViewerClasses.ViewerRec _ [], paint: BOOL _ TRUE] RETURNS [gargoyleContainer: MJSContainers.MJSContainer] = { RETURN[MJSContainers.Create[$GargoyleMJSContainer, info, paint]]; }; ChildYBound: PUBLIC PROC [gargoyleContainer: MJSContainers.MJSContainer, child: Viewer] = { MJSContainers.ChildYBound[gargoyleContainer, child]; }; ChildXBound: PUBLIC PROC [gargoyleContainer: MJSContainers.MJSContainer, child: Viewer] = { MJSContainers.ChildXBound[gargoyleContainer, child]; }; GargoyleContainerSave: PUBLIC ViewerClasses.SaveProc = { ggData: GGData; fullName: Rope.ROPE; IF BiScrollers.ViewerIsABiScroller[self] THEN { -- emergency save called through picture ggData _ NARROW[BiScrollers.ClientDataOfViewer[self]]; fullName _ IF ggData.controls.picture.file=NIL THEN Rope.Cat[FileNames.CurrentWorkingDirectory[], "SaveAllEdits-", Convert.RopeFromInt[from: (emergencyIndex _ emergencyIndex+1), base: 10, showRadix: FALSE], ".gargoyle"] ELSE ggData.controls.picture.file; } ELSE { -- emergency save called through panel ggData _ NARROW[MJSContainers.GetClientData[self]]; fullName _ IF ggData.controls.panel.file=NIL THEN Rope.Cat[FileNames.CurrentWorkingDirectory[], "SaveAllEdits-", Convert.RopeFromInt[from: (emergencyIndex _ emergencyIndex+1), base: 10, showRadix: FALSE], ".gargoyle"] ELSE ggData.controls.panel.file; }; GGEvent.Store[ggData, LIST[$Emergency, FileNames.StripVersionNumber[fullName]]]; -- save the action area }; GargoyleContainerDestroy: PUBLIC ViewerClasses.DestroyProc = { ggData: GGData _ NARROW[MJSContainers.GetClientData[self]]; IF ggData.debug.autoScriptStream#NIL THEN [ggData.debug.autoScriptStream, ggData.debug.autoScriptName] _ GGSessionLog.CloseScript[ggData.debug.autoScriptStream, ggData.debug.autoScriptName, ggData.router]; IF ggData.debug.writeScriptStream#NIL THEN [ggData.debug.writeScriptStream, ggData.debug.writeScriptName] _ GGSessionLog.CloseScript[ggData.debug.writeScriptStream, ggData.debug.writeScriptName, ggData.router]; IF ggData.controls.topper=ggData.controls.panel OR ggData.controls.picture.destroyed THEN GGUserInput.EventNotify[ggData, LIST[$Destroy]]; -- frees much garbage }; GargoyleContainerSet: PUBLIC ViewerClasses.SetProc = { child: Viewer; ggData: GGData _ NARROW[MJSContainers.GetClientData[self]]; IF data=NIL THEN RETURN; -- November 27, 1985 KAP child _ NARROW[data]; IF op=$YBound THEN ChildYBound[self, child] ELSE IF op=$XBound THEN ChildXBound[self, child] ELSE ERROR; }; emergencyIndex: INT _ 0; OpenScript: PUBLIC PROC [fileName: Rope.ROPE, ggData: GGData, oldStream: IO.STREAM _ NIL, oldScriptName: Rope.ROPE _ NIL] RETURNS [stream: IO.STREAM, fullName: Rope.ROPE] = { success: BOOL _ FALSE; IF oldStream#NIL THEN [----, ----] _ CloseScript[oldStream, oldScriptName, ggData.router]; [fullName, success] _ GGFileOps.GetScriptFileName["OpenScript", FileNames.StripVersionNumber[fileName], ggData.currentWDir, ggData.router]; IF NOT success THEN RETURN; stream _ FS.StreamOpen[fullName, $create ! FS.Error => GOTO FSError]; Feedback.PutF[ggData.router, oneLiner, $Feedback, "OpenScript: %g opened", [rope[fullName]] ]; ActionToScript[stream, LIST[$Version, NEW[REAL _ GGUtility.version]]]; CaptureSessionState[stream, ggData]; EXITS FSError => Feedback.Append[ggData.router, oneLiner, $Complaint, Rope.Concat["FSError while trying ", fileName] ]; }; AppendScriptInternal: PROC [fileName: Rope.ROPE, router: MsgRouter, wdir: Rope.ROPE _ NIL] RETURNS [stream: IO.STREAM, fullName: Rope.ROPE] = { success: BOOL _ FALSE; [fullName, success] _ GGFileOps.GetScriptFileName["AppendScript", fileName, wdir, router]; IF NOT success THEN RETURN; stream _ FS.StreamOpen[fullName, $append ! FS.Error => GOTO FSError]; EXITS FSError => Feedback.Append[router, oneLiner, $Complaint, Rope.Concat["AppendScript failed: FS Error while trying to open ", fileName] ]; }; AppendScript: PUBLIC PROC [fileName: Rope.ROPE, ggData: GGData, oldStream: IO.STREAM _ NIL, oldScriptName: Rope.ROPE] RETURNS [stream: IO.STREAM, fullName: Rope.ROPE] = { success: BOOL _ FALSE; IF oldStream#NIL THEN [----, ----] _ CloseScript[oldStream, oldScriptName, ggData.router]; [fullName, success] _ GGFileOps.GetScriptFileName["AppendScript", fileName, ggData.currentWDir, ggData.router]; IF NOT success THEN RETURN; stream _ FS.StreamOpen[fullName, $append ! FS.Error => GOTO FSError]; Feedback.PutF[ggData.router, oneLiner, $Feedback, "AppendToScript: %g opened for appending", [rope[fullName]] ]; EXITS FSError => Feedback.Append[ggData.router, oneLiner, $Complaint, Rope.Concat["AppendScript failed: FS Error while trying to open ", fileName] ]; }; CaptureSessionState: PROC [stream: IO.STREAM, ggData: GGData] = { gravExtent, scaleUnit: REAL; gravityOn, midpointsOn, heuristicsOn, showAlignments: BOOL; gravityType: GravityType; defaultFont: FontData; displayStyle: GGModelTypes.DisplayStyle; caretPoint: Point; caretNormal: Vector; strokeColor, fillColor: ImagerColor.Color; values: LIST OF REAL; on: LIST OF BOOL; names: LIST OF Rope.ROPE; transformRope: Rope.ROPE; transformRope _ GGDescribe.FactoredTransformationToRope[GGState.GetBiScrollersTransform[ggData]]; ActionToScript[stream, LIST[$SetBiScrollersTransform, transformRope]]; [values, on] _ GGState.GetSlopeAlignments[ggData]; ActionToScript[stream, LIST[$SetSlopes, GGDescribe.ScalarButtonValuesToRope[NIL, values, on]]]; [values, on] _ GGState.GetAngleAlignments[ggData]; ActionToScript[stream, LIST[$SetAngles, GGDescribe.ScalarButtonValuesToRope[NIL, values, on]]]; [names, values, on] _ GGState.GetRadiusAlignments[ggData]; ActionToScript[stream, LIST[$SetRadii, GGDescribe.ScalarButtonValuesToRope[names, values, on]]]; [names, values, on] _ GGState.GetLineDistanceAlignments[ggData]; ActionToScript[stream, LIST[$SetDistances, GGDescribe.ScalarButtonValuesToRope[names, values, on]]]; midpointsOn _ GGState.GetMidpoints[ggData]; ActionToScript[stream, LIST[$SetMidpoints, IF midpointsOn THEN "T" ELSE "F"]]; heuristicsOn _ GGState.GetHeuristics[ggData]; ActionToScript[stream, LIST[$SetHeuristics, IF heuristicsOn THEN "T" ELSE "F"]]; showAlignments _ GGState.GetShowAlignments[ggData]; ActionToScript[stream, LIST[$SetShowAlignments, IF showAlignments THEN "T" ELSE "F"]]; scaleUnit _ GGState.GetScaleUnit[ggData]; ActionToScript[stream, LIST[$SetScaleUnit, NEW[REAL _ scaleUnit], $Quietly]]; displayStyle _ GGState.GetDisplayStyle[ggData]; ActionToScript[stream, LIST[$SetDisplayStyle, GGUIUtility.DisplayStyleToRope[displayStyle]]]; gravityOn _ GGState.GetGravity[ggData]; ActionToScript[stream, LIST[$SetGravity, IF gravityOn THEN "T" ELSE "F"]]; gravExtent _ GGState.GetGravityExtent[ggData]; ActionToScript[stream, LIST[$SetGravityExtent, NEW[REAL _ gravExtent]]]; gravityType _ GGState.GetGravityType[ggData]; ActionToScript[stream, LIST[$SetGravityChoice, GGUIUtility.GravityTypeToRope[gravityType]] ]; defaultFont _ GGState.GetDefaultFont[ggData]; ActionToScript[stream, LIST[$SetDefaultFont, GGFont.FontAsLiteralRope[defaultFont]] ]; strokeColor _ GGState.GetDefaultStrokeColor[ggData]; ActionToScript[stream, LIST[$SetDefaultLineColorFromRope, GGDescribe.ColorToRope[strokeColor]] ]; fillColor _ GGState.GetDefaultFillColor[ggData]; ActionToScript[stream, LIST[$SetDefaultFillColorFromRope, GGDescribe.ColorToRope[fillColor]] ]; caretPoint _ GGCaret.GetPoint[ggData.caret]; ActionToScript[stream, LIST[$SetCaretPosition, NEW[Point _ caretPoint]] ]; caretNormal _ GGCaret.GetNormal[ggData.caret]; ActionToScript[stream, LIST[$SetCaretNormal, NEW[Vector _ caretNormal]] ]; }; CloseScript: PUBLIC PROC [stream: IO.STREAM, scriptName: Rope.ROPE, router: MsgRouter] RETURNS [newStream: IO.STREAM, newName: Rope.ROPE] = { IF stream=NIL THEN GOTO NotLogging; stream.Close[]; Feedback.PutF[router, oneLiner, $Feedback, "CloseScript: %g closed", [rope[scriptName]] ]; newStream _ NIL; newName _ NIL; EXITS NotLogging => Feedback.Append[router, oneLiner, $Feedback, "Not scripting this session"]; }; FlushScript: PUBLIC PROC [oldStream: IO.STREAM, oldScriptName: Rope.ROPE, router: MsgRouter] RETURNS [newStream: IO.STREAM, newName: Rope.ROPE] = { name: Rope.ROPE; IF oldStream # NIL THEN oldStream.Close[]; name _ FileNames.StripVersionNumber[oldScriptName]; [newStream, newName] _ AppendScriptInternal[name, router]; Feedback.Append[router, oneLiner, $Feedback, "Autoscript checkpoint"]; }; EnterAction: PUBLIC PROC [clientData: REF ANY, inputAction: REF] = { event: LIST OF REF ANY _ NARROW[inputAction]; ggData: GGData _ NARROW[clientData]; ActionToScript[ggData.debug.writeScriptStream, event]; ActionToScript[ggData.debug.autoScriptStream, event]; }; ActionToScript: PROC [stream: IO.STREAM, event: LIST OF REF ANY] = { IF stream=NIL THEN RETURN; IF event.first = $SawStartOp OR event.first = $SawSelectAll OR event.first = $SawTextFinish OR event.first = $SawMouseFinish THEN RETURN; SessionLog.EnterAction[stream, event]; }; PlayAction: PROC [clientData: REF, inputAction: REF] = { event: LIST OF REF ANY _ NARROW[inputAction]; GGUserInput.PlayAction[clientData, event]; }; PlaybackFromFile: PUBLIC PROC [fileName: Rope.ROPE, ggData: GGData] = { fullName: Rope.ROPE; success: BOOL _ FALSE; endOfStream: BOOL _ FALSE; f: IO.STREAM; startTime: BasicTime.GMT; startTimeCard: CARD; BEGIN [fullName, success] _ GGFileOps.GetScriptFileName["Playback script", fileName, ggData.currentWDir, ggData.router]; IF NOT success THEN {fullName _ fileName; GOTO OpenFileProblem}; [f, success] _ OpenExistingFile[fullName, ggData]; IF NOT success THEN GOTO OpenFileProblem; GGEvent.InitializeAlignments[ggData, LIST[$PlaybackFromFile]]; -- should only happen for old script versions ***** ggData.aborted[playback] _ FALSE; -- just in case there was one from last playback Feedback.PutF[ggData.router, oneLiner, $Feedback, "Playing: %g", [rope[fullName]] ]; startTime _ BasicTime.Now[]; startTimeCard _ BasicTime.ToNSTime[startTime]; WHILE NOT endOfStream DO endOfStream _ SessionLog.PlayAction[f, ggData, PlayAction]; IF ggData.aborted[playback] THEN { Feedback.Append[ggData.router, oneLiner, $Feedback, Rope.Cat["Aborted playback of ", fullName]]; SlackProcess.FlushQueue[ggData.slackHandle]; ggData.refresh.suppressRefresh _ FALSE; -- in case you killed FastPlayback ggData.refresh.suppressScreen _ FALSE; -- in case you killed FastPlayback ggData.aborted[playback] _ FALSE; RETURN; }; ENDLOOP; GGUserInput.PlayAction[ggData, LIST[$EndOfSessionLogMessage, fullName, NEW[CARD _ startTimeCard]]]; ggData.aborted[playback] _ FALSE; EXITS OpenFileProblem => Feedback.Append[ggData.router, oneLiner, $Complaint, Rope.Cat["Could not open ", fullName, " for playback"] ]; END; }; EndOfScriptMessage: PUBLIC PROC [ggData: GGData, event: LIST OF REF ANY] = { logName: Rope.ROPE _ NARROW[event.rest.first]; startTimeCard: CARD _ IF ISTYPE[event.rest.rest.first, REF INT] THEN NARROW[event.rest.rest.first, REF INT]^ ELSE NARROW[event.rest.rest.first, REF CARD]^; startTime: BasicTime.GMT _ BasicTime.FromNSTime[startTimeCard]; endTime: BasicTime.GMT; totalTime: INT; endTime _ BasicTime.Now[]; totalTime _ BasicTime.Period[startTime, endTime]; Feedback.PutF[ggData.router, oneLiner, $Statistics, "Finished playback of %g in time (%r)", [rope[logName]], [integer[totalTime]]]; }; OpenExistingFile: PROC [name: Rope.ROPE, ggData: GGData] RETURNS [f: IO.STREAM, success: BOOL _ FALSE] = { success _ TRUE; f _ FS.StreamOpen[name ! FS.Error => { success _ FALSE; Feedback.Append[ggData.router, oneLiner, $Complaint, error.explanation]; CONTINUE}; ]; }; SafeClose: PUBLIC PROC [stream: IO.STREAM, router: FeedbackTypes.MsgRouter _ NIL] ~ { IO.Close[stream ! IO.Error => { msg: Rope.ROPE ~ "IO.Close failed (IO.Error). Continuing anyway"; IF router=NIL THEN Feedback.AppendByName[$Gargoyle, oneLiner, $Complaint, msg] ELSE Feedback.Append[router, oneLiner, $Complaint, msg]; CONTINUE; }; FS.Error => { msg: Rope.ROPE ~ "IO.Close failed (FS.Error: %g). Continuing anyway"; IF router=NIL THEN Feedback.PutFByName[$Gargoyle, oneLiner, $Complaint, msg, [rope[error.explanation]]] ELSE Feedback.PutF[router, oneLiner, $Complaint, msg, [rope[error.explanation]]]; CONTINUE; }; ]; }; GGHomeDirectory: PUBLIC PROC RETURNS [Rope.ROPE] = { RETURN ["/CedarCommon/Gargoyle/"]; }; ParseFeedbackRope: PUBLIC PROC [rope: Rope.ROPE] RETURNS [val: REF ANY] ~ { RETURN[EBMesaLisp.Parse[IO.RIS[rope]].val]; }; Init: PROC = { gargoyleContainerClass: MJSContainers.MJSContainerClass _ NEW[MJSContainers.MJSContainerClassRep _ [ destroy: GargoyleContainerDestroy, set: GargoyleContainerSet, save: GargoyleContainerSave -- used when Shift-Shift-Swat is invoked ]]; MJSContainers.RegisterClass[$GargoyleMJSContainer, gargoyleContainerClass]; -- plug in to MJSContainers emergencyIndex _ 0; }; Init[]; END. `GGUIUtilityImpl.mesa Contents: Utility routines for the user interface level of Gargoyle. Copyright Ó 1988, 1989 by Xerox Corporation. All rights reserved. Bier, August 30, 1991 4:08 pm PDT Pier, March 29, 1990 10:44 am PST Doug Wyatt, September 14, 1989 4:27:53 pm PDT GGDescribe GGContainer Creates a new, empty container. You probably want to pass a name in the info record. constrain (child.wy + child.wh = gargoyleContainer.wh) constrain (child.wx + child.ww = gargoyleContainer.ww) after next time gargoyleContainer is painted [self: ViewerClasses.Viewer, force: BOOL _ FALSE] This SaveProc is called only by the emergency save mechanism, either directly or via GGWindowImpl.BSSaveProc. Normal saves call Store in GGEvent. Close all Playback Scripts. if there is only one viewer or there is a separate picture viewer that has been destroyed, then destroy the control panel and free the scene storage. If the separate picture is not yet destroyed, don't free the scene storage so that an Emergency save can save the scene. SetProc: TYPE = PROC [self: Viewer, data: REF ANY, finalise: BOOL _ TRUE, op: ATOM _ NIL]; GGSessionLog this PROC sets up for logging but does not start it. Client must also call SlackProcess.EnableSessionLogging to start logging events. GGEvent.InitializeAlignments[ggData, LIST[$OpenScript]]; Header showColors: BOOL; BiScrollers Alignments showColors _ GGState.GetShowColors[ggData]; ActionToScript[stream, LIST[$SetShowColors, IF showColors THEN "T" ELSE "F"]]; Default Stroke Properties go Here Default Dashing goes Here Default Shadows go Here Default Anchor goes Here Close the script, causing all actions to be written to disk. Then, open it again with a new version number. This proc can complete long before anything actually happens because of the queue, so you have to handle aborts at the abort detector. This code only gets executed if you abort while the queue is backed up. Two possiblilities 1) File doesn't exist or already open. Print error message. Fail. 2) File does exist. File it in. Succeed. returns directory name in which help material and auxiliary files may be found ÊM˜Jšœ™šÏbœ<™DJšœB™BIcode™!K™!K™-J™—šÏk ˜ Jšœ»˜»J˜—šÏnœžœž˜JšžœÆžœ/˜þKšžœK˜R—Kšž˜˜Kšœž œÏc˜EKšœ ž œ$ ˜[Kšœžœ˜1Jšœžœ˜!Kšœžœ˜#Kšœžœ#˜7Kšœžœ˜/Kšœ žœ˜*Kšœ žœ˜-Kšœ žœ˜'Kšœžœ˜'Kšœ žœ ˜1Kšœžœžœ!˜Kšœ#žœ˜Kšœžœ$˜;Kš™Kšžœžœžœ¤˜ÍKšžœ žœžœ¨˜ÒK™Kš žœ.žœ#žœ!žœ  ˜ Kšœ˜K˜—šÐbnœžœ˜6Kšœ žœžœžœžœ žœžœžœžœ™ZKšœ˜Kšœžœ$˜;Kš žœžœžœžœ ˜1Kšœžœ˜Kšžœ žœ˜+Kšžœžœ žœ˜0Kšžœžœ˜ K˜—Kšœžœ˜K˜Kšœ ™ šŸ œžœžœžœžœžœžœž œžœ žœžœžœ˜®Kšœžœ|™…Kšœ žœžœ˜Kšžœ žœžœE˜ZKšœ‹˜‹Kšžœžœ žœžœ˜Kšœ žœ žœ žœ ˜EKšœ%žœ™8Kšœ^˜^Kš™Kšœžœ žœžœ˜FKšœ$˜$šž˜Kšœq˜q—Kšœ˜K˜—šŸœžœžœ žœžœžœ žœžœžœ˜Kšœ žœžœ˜KšœZ˜ZKšžœžœ žœžœ˜Kšœ žœ žœ žœ ˜Ešž˜Kšœˆ˜ˆ—Kšœ˜K˜—K˜šŸ œžœžœžœžœžœžœžœžœ žœžœžœ˜ªKšœ žœžœ˜Kšžœ žœžœE˜ZKšœo˜oKšžœžœ žœžœ˜Kšœ žœ žœ žœ ˜EK–Ý[feedback: Feedback.FeedbackData, msgType: Feedback.MsgType, format: ROPE _ NIL, v1: IO.Value _ [null[]], v2: IO.Value _ [null[]], v3: IO.Value _ [null[]], v4: IO.Value _ [null[]], v5: IO.Value _ [null[]]]šœp˜pšž˜Kšœ˜—K˜K˜—šŸœžœ žœžœ˜AKšœžœ˜Kšœ žœ™Kšœ6žœ˜;Kšœ˜K˜K˜(K˜K˜Kšœ*˜*Kšœžœžœžœ˜Kšœžœžœžœ˜Kšœžœžœžœ˜Kšœžœ˜Kš ™ Kšœa˜aKšœžœ+˜FKš ™ Kšœœ ˜2Kšœžœ1žœ˜_Kšœœ ˜2Kšœžœ1žœ˜_Kšœœ ˜:KšœžœE˜`Kšœœ ˜@KšœžœI˜dKš œ ˜+Kš œžœžœ žœžœ˜NKš œ!˜-Kš œžœžœžœžœ˜PKšœ%˜3Kš œžœžœžœžœ˜VKš œ!™+Kš œžœžœ žœžœ™NKš œ ˜)Kšœžœžœžœ˜MKš œ#˜/KšœžœB˜]Kš œ˜'Kš œžœžœ žœžœ˜JKš œ$˜.Kšœžœžœžœ˜HKš œ"˜-KšœžœB˜]Kš œ"˜-Kšœžœ;˜VKš œ)˜4KšœžœF˜aKš!™!Kš œ'˜0KšœžœD˜_Kš™Kš™Kš™Kšœ,˜,Kšœžœžœ˜JKšœ.˜.Kšœžœžœ˜JK˜K˜—šŸ œžœžœ žœžœžœžœ žœžœžœ˜Kšžœžœžœžœ ˜#Kšœ˜K–Ý[feedback: Feedback.FeedbackData, msgType: Feedback.MsgType, format: ROPE _ NIL, v1: IO.Value _ [null[]], v2: IO.Value _ [null[]], v3: IO.Value _ [null[]], v4: IO.Value _ [null[]], v5: IO.Value _ [null[]]]šœZ˜ZKšœ žœ˜Kšœ žœ˜šž˜KšœY˜Y—K˜K˜—šŸ œžœžœ žœžœžœžœ žœžœžœ˜“K™lKšœ žœ˜Kšžœ žœžœ˜*Kšœ3˜3Kšœ:˜:KšœF˜FK˜K˜—š Ÿ œžœžœžœžœžœ˜DKš œžœžœžœžœžœ˜-Kšœžœ ˜$Kšœ6˜6Kšœ5˜5K˜K˜—šŸœžœ žœžœ žœžœžœžœ˜DKšžœžœžœžœ˜Kš žœžœžœžœžœžœ˜‰Kšœ&˜&K˜K˜—šŸ œžœžœžœ˜8Kš œžœžœžœžœžœ˜-Kšœ*˜*K˜K˜—šŸœžœžœžœ˜GKšœžœ˜Kšœ žœžœ˜Kšœ žœžœ˜Kšœžœžœ˜ Kšœžœ˜Kšœžœ˜šž˜Kšœr˜rKšžœžœ žœžœ˜@Kšœ2˜2Kšžœžœ žœžœ˜)Kšœ%žœ -œ˜rKšœžœ 0˜RK–Ý[feedback: Feedback.FeedbackData, msgType: Feedback.MsgType, format: ROPE _ NIL, v1: IO.Value _ [null[]], v2: IO.Value _ [null[]], v3: IO.Value _ [null[]], v4: IO.Value _ [null[]], v5: IO.Value _ [null[]]]šœT˜TKš˜Kšœ.˜.šžœžœ ž˜Kšœœ˜;šžœžœ˜"KšœÏ™ÏKšœ`˜`Kšœ,˜,Kšœ!žœ "˜JKšœ žœ "˜IKšœžœ˜!Kšžœ˜K˜—Kšžœ˜—Kšœžœ$žœžœ˜cKšœžœ˜!šž˜Kšœ˜—Kšžœ˜—Kšœ˜K˜—šŸœžœžœžœžœžœžœ˜LKšœžœžœ˜.Kšœžœžœžœžœžœžœžœžœžœžœžœžœžœ˜›Kšœžœ'˜?Kšœžœ˜Kšœ žœ˜Kš˜Kšœ1˜1Kšœƒ˜ƒK˜K˜—šŸœžœ žœžœžœžœ žœžœ˜jšœ™KšœC™CKšœ+™+—Kšœ žœ˜šœžœžœ ˜&Kšœ žœ˜KšœH˜HKšžœ˜ Kšœ˜—K˜—K˜š Ÿ œžœžœ žœžœ$žœ˜Ušžœ˜šžœ ˜ Kšœ žœ4˜Bšžœž˜ Kšžœ<˜@Kšžœ4˜8—Kšžœ˜ Kšœ˜—šžœ ˜ Kšœ žœ8˜Fšžœž˜ KšžœU˜YKšžœM˜Q—Kšžœ˜ Kšœ˜—Kšœ˜—K˜—K˜š Ÿœžœžœžœžœ˜4K™NKšžœ˜"K˜K™—šŸœžœžœ žœžœžœžœ˜KJšžœžœžœ ˜+K˜K˜—šŸœžœ˜šœ:žœ'˜dKšœ"˜"Kšœ˜Kšœ (˜DKšœ˜—KšœL ˜gKšœ˜K˜—K˜Kšœ˜K˜Kšžœ˜K˜—…—F–eC