<> <> <> <> <<>> DIRECTORY Atom USING [GetPropFromList, PutPropOnList], Carets USING [ResumeCarets, SuspendCarets], Cursors USING [InvertCursor], InputFocus USING [GetInputFocus, SetInputFocus], Process USING [GetPriority, Priority, priorityForeground, SetPriority], RefTab USING [Create, Fetch, Ref, Store], Rope USING [Compare, ROPE], RTOS USING [GetCurrent, RegisterCedarProcess, UnregisterCedarProcess], TIPUser USING [TIPScreenCoords], ViewerEvents USING [ProcessEvent], ViewerOps, ViewerLocks, MenusPrivate USING [ViewerMenus], ViewerClasses, ViewerSpecs, WindowManager USING [colorDisplayOn], WindowManagerPrivate; ViewerOpsImplB: CEDAR PROGRAM IMPORTS Atom, Carets, Cursors, InputFocus, Process, RefTab, Rope, RTOS, ViewerEvents, ViewerLocks, ViewerOps, WindowManager, WindowManagerPrivate EXPORTS ViewerOps SHARES ViewerEvents = BEGIN OPEN ViewerClasses, ViewerSpecs, ViewerOps; classTable: RefTab.Ref _ RefTab.Create[mod:50]; -- hold viewer classes RegisterViewerClass: PUBLIC PROC [flavor: ViewerFlavor, class: ViewerClass, superClassFlavor: ViewerFlavor _ NIL] = { <> class.flavor _ flavor; IF superClassFlavor#NIL THEN { superClass: ViewerClass = FetchViewerClass[superClassFlavor]; class.parent _ superClass; IF class.notify=NIL THEN class.notify _ superClass.notify; IF class.paint=NIL THEN class.paint _ superClass.paint; IF class.modify=NIL THEN class.modify _ superClass.modify; IF class.destroy=NIL THEN class.destroy _ superClass.destroy; IF class.copy=NIL THEN class.copy _ superClass.copy; IF class.set=NIL THEN class.set _ superClass.set; IF class.get=NIL THEN class.get _ superClass.get; IF class.save=NIL THEN class.save _ superClass.save; IF class.scroll=NIL THEN class.scroll _ superClass.scroll; IF class.hscroll=NIL THEN class.hscroll _ superClass.hscroll; IF class.caption=NIL THEN class.caption _ superClass.caption; }; [] _ 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]]}; <> <<>> IsClass: PUBLIC PROC [viewer: Viewer, class: ViewerFlavor] RETURNS[BOOL] = { flavor: ViewerFlavor = class; -- should change the parameter name to flavor FOR class: ViewerClass _ viewer.class, class.parent UNTIL class=NIL DO IF class.flavor=flavor THEN RETURN[TRUE]; ENDLOOP; RETURN[FALSE]; }; EnumerateViewers: PUBLIC PROC [enum: EnumProc] = { <> 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; }; EnumerateChildren: PUBLIC PROC [viewer: Viewer, enum: EnumProc] = { v: Viewer _ viewer.child; next: Viewer; WHILE v#NIL DO next _ v.sibling; EnumerateChildren[v, enum]; IF ~enum[v] THEN RETURN; v _ next; ENDLOOP; }; FindViewer: PUBLIC PROC [name: Rope.ROPE] RETURNS [viewer: Viewer] = { MatchName: EnumProc = { IF Rope.Compare[name, v.name, FALSE]=equal THEN { viewer _ v; RETURN[FALSE]; } ELSE RETURN[TRUE]; }; EnumerateViewers[MatchName]; }; <<>> SaveViewer: PUBLIC PROC [viewer: Viewer] = { list: LIST OF Viewer; ok: BOOL _ FALSE; 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; v.saveInProgress _ FALSE; IF ok THEN v.newVersion _ v.newFile _ 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 ok _ viewer.class.save[viewer]; LockedStop[]; }; RestoreViewer: PUBLIC PROC [viewer: Viewer] = { DoOne: PROC [v: Viewer] = INLINE { KillInputFocus[v]; IF v.class.init # NIL THEN v.class.init[v]; v.newVersion _ v.newFile _ FALSE; PaintViewer[v, all]; }; DoOne[viewer]; IF viewer.link#NIL THEN FOR v: Viewer _ viewer.link, v.link UNTIL v=viewer DO DoOne[v]; ENDLOOP; }; KillInputFocus: PROC [viewer: Viewer] = { focus: Viewer _ InputFocus.GetInputFocus[].owner; WHILE focus # NIL DO IF focus # viewer THEN focus _ focus.parent ELSE {InputFocus.SetInputFocus[]; EXIT}; ENDLOOP; }; IndicateNewVersion: PUBLIC PROC [viewer: Viewer] = { 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]; }; SetNewFile: PUBLIC PROC [viewer: Viewer] = { DoOne: PROC [v: Viewer] = { v.newFile _ TRUE; PaintViewer[v, caption]; }; DoOne[viewer]; IF viewer.link#NIL THEN FOR v: Viewer _ viewer.link, v.link UNTIL v=viewer DO DoOne[v]; ENDLOOP; }; SetOpenHeight: PUBLIC PROC [viewer: Viewer, clientHeight: INTEGER] = { overhead: INTEGER _ captionHeight + (IF viewer.border THEN windowBorderSize ELSE 0); IF viewer.menus#NIL THEN overhead _ overhead+NARROW[viewer.menus, MenusPrivate.ViewerMenus].h+menuBarHeight; viewer.openHeight _ clientHeight+overhead; }; SaveAllEdits: PUBLIC PROC = { <> old: Process.Priority = Process.GetPriority[]; Save: EnumProc = { 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]; }; IF old>Process.priorityForeground THEN TRUSTED { -- called from CoPilot Process.SetPriority[Process.priorityForeground]; RTOS.RegisterCedarProcess[RTOS.GetCurrent[]]; }; EnumerateViewers[Save]; IF old>Process.priorityForeground THEN TRUSTED { -- called from CoPilot RTOS.UnregisterCedarProcess[RTOS.GetCurrent[]]; Process.SetPriority[old]; }; }; PaintEverything: PUBLIC PROC = { 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[]; }; <> <> <> <> <> <> <> <> <> <> <> <> <<};>> <<>> UserToScreenCoords: PUBLIC PROC[self: Viewer, vx, vy: INTEGER _ 0] RETURNS[sx, sy: INTEGER] = { UNTIL self=NIL DO -- compute enclosing viewer offsets vx _ vx + self.cx; vy _ vy + self.cy; self _ self.parent; ENDLOOP; RETURN [vx, vy]; }; <> <> < NULL;>> <> <> <> <<>> <> <> <> <> <> < RETURN[NIL];>> <> <<};>> <<>> <> <<{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))]};>> <<>> <> <<{RETURN[y IN [viewer.cy..viewer.cy+viewer.ch) AND>> <> <<>> <> <> <<>> <> <<{RETURN[ex IN [v.wx..v.wx+v.ww) AND ey IN [v.wy..v.wy+v.wh)]};>> <<>> <> <> <> <> <> <<>> <> <> <> <> <> <> <> <<};>> <> <> <<};>> <<>> <> <<>> <> <> <<>> <> <> <> <<>> <> <> <> <> <<>> <<};>> <<>> Display: TYPE = {default, color}; <<>> <> <> < NULL;>> <> <> <> <> <> <> <> <> <> <> <<};>> <> <> <> <> <> <> <> <<};>> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <<>> <> <<{ invert: BOOL = IF viewer.parent=NIL THEN client AND viewer.class.coordSys=top>> <> <> <> <> <> <> <<};>> <<};>> <<>> MouseInViewer: PUBLIC PROC[tsc: TIPUser.TIPScreenCoords] RETURNS[viewer: Viewer _ NIL, client: BOOL _ FALSE] = { ENABLE UNWIND => NULL; TopLevelHit: PROC[x, y: INTEGER, d: Display] RETURNS[Viewer] = { FOR column: Column DECREASING IN Column DO head: Viewer = WindowManagerPrivate.rootViewerTree[column]; -- head of column list FOR v: Viewer _ head, v.sibling UNTIL v=NIL DO vd: Display = (IF v.column=color AND NOT v.iconic THEN color ELSE default); IF d=vd AND x IN[v.wx..v.wx+v.ww) AND y IN[v.wy..v.wy+v.wh) THEN RETURN[v]; ENDLOOP; ENDLOOP; RETURN[NIL]; }; Client: PROC[v: Viewer, x, y: INTEGER] RETURNS [BOOL] = INLINE { RETURN[y IN [v.cy..v.cy+v.ch) AND x IN [v.cx..v.cx+v.cw)] }; ChildHit: PROC[parent: Viewer, x, y: INTEGER] RETURNS[Viewer] = { FOR v: Viewer _ parent.child, v.sibling UNTIL v=NIL DO IF x IN[v.wx..v.wx+v.ww) AND y IN[v.wy..v.wy+v.wh) THEN RETURN[v]; ENDLOOP; RETURN[NIL]; }; x: INTEGER _ tsc.mouseX; y: INTEGER _ tsc.mouseY; viewer _ TopLevelHit[x, y, (IF tsc.color THEN color ELSE default)]; IF viewer=NIL THEN RETURN[NIL, FALSE]; WHILE (client _ Client[viewer, x, y]) AND NOT viewer.iconic AND viewer.child#NIL DO <> ex: INTEGER = x-viewer.cx; ey: INTEGER = y-viewer.cy; child: Viewer = ChildHit[viewer, ex, ey]; IF child=NIL THEN EXIT; viewer _ child; x _ ex; y _ ey; ENDLOOP; <> IF client THEN { tsc.mouseX _ x-viewer.cx; tsc.mouseY _ y-viewer.cy } ELSE { tsc.mouseX _ x-viewer.wx; tsc.mouseY _ y-viewer.wy }; }; AddProp: PUBLIC PROC [viewer: Viewer, prop: ATOM, val: REF ANY] = { viewer.props _ Atom.PutPropOnList[viewer.props, prop, val]} ; <> FetchProp: PUBLIC PROC [viewer: Viewer, prop: ATOM] RETURNS [val: REF ANY] = { RETURN[Atom.GetPropFromList[viewer.props, prop]]} ; <> <> <> <> <> <> <> <> <> <> <<};>> END.