DIRECTORY Carets USING [ResumeCarets, SuspendCarets], Cursors USING [InvertCursor], InputFocus USING [GetInputFocus, SetInputFocus], Menus USING [CopyMenu, Menu], MessageWindow USING [Append, Blink], Process USING [GetPriority, Priority, priorityForeground, SetPriority], RefTab USING [Create, Fetch, Ref, Store], Rope USING [Compare, ROPE], TIPUser USING [TIPScreenCoords], ViewerEvents USING [ProcessEvent], ViewerOps, ViewerLocks, ViewerClasses, ViewerClassesExtras USING [], ViewerSpecs, WindowManager USING [colorDisplayOn], WindowManagerPrivate; ViewerOpsImplB: CEDAR PROGRAM IMPORTS Carets, Cursors, InputFocus, Menus, MessageWindow, Process, RefTab, Rope, ViewerEvents, ViewerLocks, ViewerOps, WindowManager, WindowManagerPrivate EXPORTS ViewerOps, ViewerClassesExtras SHARES Menus, ViewerEvents = BEGIN OPEN ViewerClasses, ViewerSpecs, ViewerOps, WindowManager; ROPE: TYPE = Rope.ROPE; classTable: RefTab.Ref _ RefTab.Create[mod:50]; -- hold viewer classes RegisterViewerClass: PUBLIC PROC [flavor: ViewerFlavor, class: ViewerClass] = { class.flavor _ flavor; [] _ RefTab.Store[classTable, flavor, class]}; FetchViewerClass: PUBLIC PROC [flavor: ViewerFlavor] RETURNS [ViewerClass] = {IF flavor = $TypeScript THEN flavor _ $Typescript; RETURN[NARROW[RefTab.Fetch[classTable, flavor].val]]}; EnumerateViewers: PUBLIC PROC [enum: EnumProc] = BEGIN FOR c: Column DECREASING IN Column DO -- decreasing so will try static viewers last v: Viewer _ WindowManagerPrivate.rootViewerTree[c]; next: Viewer; UNTIL v=NIL DO next _ v.sibling; IF ~enum[v] THEN RETURN; v _ next; ENDLOOP; ENDLOOP; END; EnumerateChildren: PUBLIC PROC [viewer: Viewer, enum: EnumProc] = BEGIN v: Viewer _ viewer.child; next: Viewer; WHILE v#NIL DO next _ v.sibling; EnumerateChildren[v, enum]; IF ~enum[v] THEN RETURN; v _ next; ENDLOOP; END; FindViewer: PUBLIC PROC [name: Rope.ROPE] RETURNS [viewer: Viewer] = BEGIN MatchName: EnumProc = BEGIN IF Rope.Compare[name, v.name, FALSE]=equal THEN BEGIN viewer _ v; RETURN[FALSE]; END ELSE RETURN[TRUE]; END; EnumerateViewers[MatchName]; END; SaveAborted: PUBLIC ERROR[error: ROPE] = CODE; -- exported to ViewerClassesExtras SaveViewer: PUBLIC PROC [viewer: Viewer] = BEGIN list: LIST OF Viewer; errorMessage: ROPE _ NIL; LockedStart: PROC = { FOR v: Viewer _ viewer, v.link DO v.saveInProgress _ TRUE; PaintViewer[v, caption, FALSE]; list _ CONS[v, list]; IF v.link = NIL OR v.link = viewer THEN EXIT; ENDLOOP}; LockedStop: PROC = { FOR saved: LIST OF Viewer _ list, saved.rest UNTIL saved = NIL DO v: Viewer = saved.first; IF v.destroyed THEN LOOP; IF errorMessage=NIL THEN v.newVersion _ v.newFile _ FALSE; v.saveInProgress _ FALSE; PaintViewer[v, caption, FALSE]; [] _ ViewerEvents.ProcessEvent[save, v, FALSE]; ENDLOOP}; FOR v: Viewer _ viewer, v.link DO IF ViewerEvents.ProcessEvent[save, v, TRUE].abort THEN RETURN; IF v.link = NIL OR v.link = viewer THEN EXIT; ENDLOOP; LockedStart[]; IF viewer.class.save=NIL THEN errorMessage _ "no save procedure in viewer class" ELSE viewer.class.save[viewer ! SaveAborted => { errorMessage _ error; CONTINUE }]; IF errorMessage#NIL THEN { MessageWindow.Append["Can't SAVE -- ", TRUE]; MessageWindow.Append[errorMessage]; MessageWindow.Blink[]; }; LockedStop[]; END; RestoreViewer: PUBLIC PROC [viewer: Viewer] = BEGIN DoOne: PROC [v: Viewer] = INLINE BEGIN KillInputFocus[v]; IF v.class.init # NIL THEN v.class.init[v]; v.newVersion _ v.newFile _ FALSE; PaintViewer[v, all]; END; DoOne[viewer]; IF viewer.link#NIL THEN FOR v: Viewer _ viewer.link, v.link UNTIL v=viewer DO DoOne[v]; ENDLOOP; END; KillInputFocus: PROC [viewer: Viewer] = BEGIN focus: Viewer _ InputFocus.GetInputFocus[].owner; WHILE focus # NIL DO IF focus # viewer THEN focus _ focus.parent ELSE {InputFocus.SetInputFocus[]; EXIT}; ENDLOOP; END; SetMenu: PUBLIC PROC [viewer: Viewer, menu: Menus.Menu, paint: BOOL _ TRUE] = BEGIN sameSize: BOOL = (menu#NIL AND viewer.menu#NIL AND viewer.menu.linesUsed=menu.linesUsed); IF viewer.iconic THEN paint _ FALSE; IF viewer.parent#NIL THEN ERROR; viewer.menu _ IF menu=NIL THEN NIL ELSE Menus.CopyMenu[menu]; IF ~sameSize AND paint THEN EstablishViewerPosition[viewer, viewer.wx, viewer.wy, viewer.ww, viewer.wh]; IF paint THEN PaintViewer[viewer, IF sameSize THEN menu ELSE all]; END; IndicateNewVersion: PUBLIC PROC [viewer: Viewer] = BEGIN link1, link2: Viewer; LockedNewVersion: PROC = { FOR v: Viewer _ viewer, v.link DO v.newVersion _ TRUE; PaintViewer[v, caption]; [] _ ViewerEvents.ProcessEvent[edit, v, FALSE]; IF v.link = NIL OR v.link = viewer THEN EXIT; ENDLOOP}; FOR v: Viewer _ viewer, v.link DO IF ViewerEvents.ProcessEvent[edit, v, TRUE].abort THEN RETURN; IF v.link = NIL OR v.link = viewer THEN EXIT; ENDLOOP; IF viewer # NIL THEN link1 _ viewer.link; IF link1 # NIL THEN link2 _ link1.link; ViewerLocks.CallUnderReadLocks[LockedNewVersion, viewer, link1, link2]; END; SetNewFile: PUBLIC PROC [viewer: Viewer] = BEGIN DoOne: PROC [v: Viewer] = BEGIN v.newFile _ TRUE; PaintViewer[v, caption]; END; DoOne[viewer]; IF viewer.link#NIL THEN FOR v: Viewer _ viewer.link, v.link UNTIL v=viewer DO DoOne[v]; ENDLOOP; END; SetOpenHeight: PUBLIC PROC [viewer: Viewer, clientHeight: INTEGER] = BEGIN overhead: INTEGER _ captionHeight + (IF viewer.border THEN windowBorderSize ELSE 0); IF viewer.menu#NIL THEN overhead _ overhead+(viewer.menu.linesUsed*menuHeight)+menuBarHeight; viewer.openHeight _ clientHeight+overhead; END; SaveAllEdits: PUBLIC PROC = BEGIN old: Process.Priority = Process.GetPriority[]; Save: EnumProc = BEGIN Cursors.InvertCursor[]; IF (v.newVersion OR v.newFile) AND v.class.save # NIL THEN v.class.save[v, TRUE ! ANY => CONTINUE]; v.newVersion _ v.newFile _ FALSE; IF v.icon=dirtyDocument THEN v.icon _ document; IF v.link#NIL THEN FOR t: Viewer _ v.link, t.link UNTIL t=v DO t.newVersion _ t.newFile _ FALSE; ENDLOOP; Cursors.InvertCursor[]; RETURN[TRUE]; END; IF old>Process.priorityForeground THEN TRUSTED BEGIN -- called from CoPilot Process.SetPriority[Process.priorityForeground]; END; EnumerateViewers[Save]; IF old>Process.priorityForeground THEN TRUSTED BEGIN -- called from CoPilot Process.SetPriority[old]; END; END; PaintEverything: PUBLIC PROC = BEGIN OPEN Process; ResetPaintCache[]; Carets.SuspendCarets[]; GreyScreen[0, 0, 9999, 9999, FALSE, FALSE]; ComputeColumn[static]; ComputeColumn[left]; ComputeColumn[right]; IF WindowManager.colorDisplayOn THEN ComputeColumn[color]; WaitForPaintingToFinish[]; Carets.ResumeCarets[]; END; UserToScreenCoords: PUBLIC PROC [self: Viewer, vx, vy: INTEGER _ 0] RETURNS [sx, sy: INTEGER] = BEGIN invert: BOOL; UNTIL self=NIL DO -- compute enclosing viewer offsets invert _ IF self.parent=NIL THEN self.class.coordSys=top ELSE self.class.coordSys#self.parent.class.coordSys; vx _ vx + self.cx; IF invert THEN vy _ Top2Bottom[self, vy]; vy _ vy + self.cy; self _ self.parent; ENDLOOP; RETURN [vx, vy]; END; MouseInViewer: PUBLIC PROC [tsc: TIPUser.TIPScreenCoords] RETURNS [viewer: Viewer, client: BOOL] = BEGIN ENABLE UNWIND => NULL; x: INTEGER _ tsc.mouseX; y: INTEGER _ tsc.mouseY; invert: BOOL; TopLevelHit: PROC RETURNS [Viewer] = BEGIN FOR c: Column DECREASING IN Column DO FOR v: Viewer _ WindowManagerPrivate.rootViewerTree[c], v.sibling UNTIL v=NIL DO IF ViewerHit[v] THEN RETURN[v]; ENDLOOP; REPEAT FINISHED => RETURN[NIL]; ENDLOOP; END; ViewerHit: PROC [v: Viewer] RETURNS [BOOL] = INLINE {RETURN[x IN [v.wx..v.wx+v.ww) AND y IN [v.wy..v.wy+v.wh) AND (IF tsc.color THEN (v.column=color AND ~v.iconic) ELSE (v.column#color OR v.iconic))]}; Client: PROC RETURNS [BOOL] = INLINE {RETURN[y IN [viewer.cy..viewer.cy+viewer.ch) AND x IN [viewer.cx..viewer.cx+viewer.cw)]}; CheckViewersChildren: PROC [v: Viewer] RETURNS [BOOL] = BEGIN ex, ey: INTEGER; EmbeddedViewerHit: PROC [v: Viewer] RETURNS [BOOL] = INLINE {RETURN[ex IN [v.wx..v.wx+v.ww) AND ey IN [v.wy..v.wy+v.wh)]}; ex _ x - v.cx; ey _ y - v.cy; invert _ IF v.parent=NIL THEN v.class.coordSys=top ELSE v.class.coordSys#v.parent.class.coordSys; IF invert THEN ey _ Bottom2Top[v, ey]; FOR v _ v.child, v.sibling UNTIL v=NIL DO IF EmbeddedViewerHit[v] THEN BEGIN x _ ex; y _ ey; viewer _ v; RETURN[TRUE]; END; ENDLOOP; RETURN[FALSE]; END; IF (viewer _ TopLevelHit[]) = NIL THEN RETURN [NIL, FALSE]; IF viewer.child#NIL AND ~viewer.iconic AND Client[] THEN WHILE viewer.child#NIL AND CheckViewersChildren[viewer] DO ENDLOOP; client _ Client[]; invert _ IF viewer.parent=NIL THEN client AND viewer.class.coordSys=top ELSE viewer.class.coordSys#viewer.parent.class.coordSys; tsc.mouseX _ x - (IF client THEN viewer.cx ELSE viewer.wx); y _ y - (IF client THEN viewer.cy ELSE viewer.wy); tsc.mouseY _ IF ~invert THEN y ELSE IF client THEN Top2Bottom[viewer, y] ELSE viewer.wh-y; END; END . . . <ViewerOpsImplB.mesa; Written by Maxwell Edited by Maxwell, May 18, 1983 9:19 am Edited by Paul Rovner, June 16, 1983 9:46 am Edited by Doug Wyatt, December 13, 1983 5:59 pm let the Viewer package know about a new class of viewer. class information from an existing viewer class. Safe in that caller can move the enumerated viewer in the tree in which case all viewers get seen at least once Not called under locks so viewers can be saved when the column is locked. poor man's crash recovery embedded frames are client info relative overwrite screen coords record Ê B˜JšÏc'™'J™'J™,J™/J™šÏk ˜ Jšœžœ˜+Jšœžœ˜Jšœ žœ ˜0Jšœžœ˜Jšœžœ˜$Jšœžœ:˜GJšœžœ˜)Jšœžœ žœ˜Jšœžœ˜ Jšœ žœ˜"J˜ J˜ J˜Jšœžœ˜J˜ Jšœžœ˜%J˜J˜—Jšœž ˜J˜Jšžœ”˜›Jšžœ˜&Jšžœ˜J˜Jšžœžœ6˜@J˜Jšžœžœžœ˜J˜šœ0˜GJ˜—šÏnœžœžœ/˜OJ˜J˜.Jš8™8J˜—šŸœžœžœžœ˜LJšœžœžœ˜3Jšžœžœ)˜6Jš0™0—J™šŸœžœžœž˜6Jšo™oš žœ ž œžœžœ-˜SJšœ3˜3J˜ šžœžœž˜J˜Jšžœ žœžœ˜J˜ Jšžœ˜—Jšžœ˜—Jšžœ˜J˜—šŸœžœžœ$ž˜GJ˜Jšœ ž˜ šžœžœž˜J˜J˜Jšžœ žœžœ˜J˜ Jšžœ˜—Jšžœ˜J˜—š Ÿ œžœžœ žœžœž˜Jšœž˜šžœžœžœž˜5J˜ Jšžœžœ˜Jšž˜—Jšžœžœžœ˜Jšžœ˜—J˜Jšžœ˜—J™Jš œ žœžœžœžœ"˜QJ˜šŸ œžœžœž˜0Jšœžœžœ˜Jšœžœžœ˜J˜šŸ œžœ˜šžœž˜!Jšœžœ˜Jšœžœ˜Jšœžœ ˜Jš žœ žœžœžœžœ˜-Jšžœ˜ ——šŸ œžœ˜š žœžœžœžœ žœž˜AJšœ˜Jšžœ žœžœ˜Jšžœžœžœžœ˜:Jšœžœ˜Jšœžœ˜Jšœ(žœ˜/Jšžœ˜ J˜——šžœž˜!Jšžœ$žœžœžœ˜>Jš žœ žœžœžœžœ˜-Jšžœ˜—J˜JšœI™IJšœ˜Jšžœžœžœ3˜PJšžœCžœ˜Sšžœžœžœ˜Jšœ'žœ˜-Jšœ#˜#J˜Jšœ˜—Jšœ ˜ J˜Jšžœ˜J˜—šŸ œžœžœž˜3šŸœžœžœž˜&Jšœ˜Jšžœžœžœ˜+Jšœžœ˜!J˜Jšžœ˜—J˜šžœ žœž˜Jšžœ!žœ žœ žœ˜H—Jšžœ˜J˜—šŸœžœž˜-Jšœ1˜1šžœ žœž˜šžœžœ˜+Jšžœžœ˜(—Jšžœ˜—Jšžœ˜—J˜š Ÿœžœžœ+žœžœž˜Sš œ žœ žœžœ žœž˜2J˜&—Jšžœžœ žœ˜$Jšžœžœžœžœ˜ Jš œžœžœžœžœžœ˜=šžœ žœž˜J˜L—Jš žœžœžœ žœžœ˜BJšžœ˜J˜—šŸœžœžœž˜8J˜šŸœžœ˜šžœž˜!Jšœžœ˜J˜Jšœ(žœ˜/Jš žœ žœžœžœžœ˜-Jšžœ˜ —J˜—šžœž˜!Jšžœ$žœžœžœ˜>Jš žœ žœžœžœžœ˜-Jšžœ˜—J˜Jšžœ žœžœ˜)Jšžœ žœžœ˜'J˜JšœG˜GJšžœ˜J˜—šŸ œžœžœž˜0šŸœžœž˜Jšœ žœ˜J˜Jšžœ˜—J˜šžœ žœž˜Jšžœ!žœ žœ žœ˜H—Jšžœ˜J˜—š Ÿ œžœžœ žœž˜JJš œ žœžœžœžœ˜Tšžœ žœžœ ˜"J˜:—J˜*Jšžœ˜—J˜šŸ œžœžœž˜!Jš™J˜.šœž˜J˜šžœžœ žœž˜5Jšžœžœžœžœ˜-—Jšœžœ˜!Jšžœžœ˜/š žœžœžœžœžœž˜>Jšœžœ˜!Jšžœ˜—J˜Jšžœžœ˜ Jšžœ˜—šžœ žœž œ˜KJšœ0˜0Jšžœ˜—J˜šžœ žœž œ˜KJšœ˜Jšžœ˜—Jšžœ˜J˜—š Ÿœžœžœžœžœ ˜2J˜J˜Jšœžœžœ˜+Jšœ˜J˜J˜Jšžœžœ˜:J˜J˜Jšžœ˜J˜—šŸœžœžœžœ˜CJšžœ žœž˜!Jšœžœ˜ šžœžœžœ#˜5šœ žœ žœžœ˜8Jšžœ0˜4—J˜Jšžœžœ˜)J˜J˜Jšžœ˜—Jšžœ ˜Jšžœ˜J˜—šŸ œžœžœ˜9Jšžœžœž˜.Jšžœžœžœ˜Jšœžœ˜Jšœžœ˜Jšœžœ˜ J˜šŸ œžœžœ ž˜*šžœ ž œžœž˜%šžœ?žœžœž˜PJšžœžœžœ˜Jšžœ˜—Jšžœžœžœžœ˜Jšžœ˜—Jšžœ˜—J˜š Ÿ œžœ žœžœž˜3š œžœžœžœžœž˜=Jš œžœ žœžœ žœžœ˜WJ˜——š Ÿœžœžœžœž˜$šœžœžœ"ž˜1Jšœžœ$˜(J˜——š Ÿœžœ žœžœž˜=Jšœžœ˜J˜š Ÿœžœ žœžœž˜;Jš œžœžœžœžœ˜>J˜—J˜J˜šœ žœ žœžœ˜2Jšžœ*˜.—Jšžœžœ˜&J˜šžœžœžœž˜)šžœžœž˜"Jš(™(J˜J˜J˜ Jšžœžœ˜ Jšžœ˜—Jšžœ˜—Jšžœžœ˜Jšžœ˜J˜—Jš žœžœžœžœžœžœ˜;J˜š žœžœžœžœ žœžœž˜OJšžœžœžœ˜,J˜—J˜š œ žœžœžœžœ˜GJšžœ4˜8J˜—Jš™Jšœžœžœ žœ ˜;Jšœ žœžœ žœ ˜2Jš œ žœ žœžœžœžœžœ ˜ZJ˜Jšžœ˜—J˜Jšžœ˜ —…—"21°