DIRECTORY ViewerClasses USING [Viewer], ViewerOps, List USING [AList, PutAssoc, Assoc], MathDisplayExpr, ViewExprOps; ViewExprOpsImpl: CEDAR PROGRAM IMPORTS ViewerOps, MathDisplayExpr, List EXPORTS ViewExprOps ~ BEGIN Viewer: TYPE ~ ViewerClasses.Viewer; DisplayExpr: TYPE ~ MathDisplayExpr.DisplayExpr; Selection: TYPE ~ REF SelectionRep; SelectionRep: TYPE ~ RECORD [ active: BOOL _ FALSE, -- TRUE iff selection is currently active flavor: ATOM, -- type of selection viewer: Viewer _ NIL, -- viewer containing selection expr: DisplayExpr _ NIL -- selected expression within viewer ]; paintQueue: LIST OF Viewer _ NIL; -- list of viewers waiting to be painted GlobalSelections: List.AList _ NIL; -- list of active selections SelectionFlavors: LIST OF ATOM _ NIL; -- list of each flavor in GlobalSelections PaintEnqueue: PUBLIC PROC[v: Viewer] ~ { FOR l: LIST OF Viewer _ paintQueue, l.rest UNTIL l = NIL DO IF v = l.first THEN RETURN; -- don't need to enqueue if already waiting ENDLOOP; paintQueue _ CONS[v, paintQueue]; }; PaintDequeue: PUBLIC PROC[v: Viewer] ~ { newQueue: LIST OF Viewer _ NIL; FOR l: LIST OF Viewer _ paintQueue, l.rest UNTIL l = NIL DO IF v # l.first THEN newQueue _ CONS[l.first, newQueue]; ENDLOOP; paintQueue _ newQueue; }; FlushPaintQueue: PUBLIC PROC[] ~ { FOR l: LIST OF Viewer _ paintQueue, l.rest UNTIL l = NIL DO ViewerOps.PaintViewer[l.first, client]; ENDLOOP; paintQueue _ NIL; }; noSelection: PUBLIC ERROR = CODE; GetSelection: PUBLIC PROC[flavor: ATOM] RETURNS[Viewer, DisplayExpr] ~ { selection: Selection _ NARROW[List.Assoc[key: flavor, aList: GlobalSelections]]; IF (selection # NIL) AND (selection.active) THEN RETURN[selection.viewer, selection.expr]; ERROR noSelection; -- no active selection of type flavor exists }; Active: PUBLIC PROC[flavor: ATOM] RETURNS[BOOL] ~ { selection: Selection _ NARROW[List.Assoc[key: flavor, aList: GlobalSelections]]; IF (selection # NIL) AND (selection.active) THEN RETURN[TRUE] ELSE RETURN[FALSE]; }; Select: PUBLIC PROC[flavor: ATOM, viewer: Viewer, expr: DisplayExpr] ~ { oldSelection: Selection _ NARROW[List.Assoc[key: flavor, aList: GlobalSelections]]; newSelection: Selection _ NEW[SelectionRep _ [active: TRUE, flavor: flavor, viewer: viewer, expr: expr]]; IF ~expr.Selectable[] THEN newSelection _ NIL; GlobalSelections _ List.PutAssoc[key: flavor, val: newSelection, aList: GlobalSelections]; AddNewFlavor[flavor]; -- update "all flavors" list IF (oldSelection # NIL) AND (oldSelection.active) THEN PaintEnqueue[oldSelection.viewer]; IF newSelection.active THEN PaintEnqueue[newSelection.viewer]; }; UnSelect: PUBLIC PROC[flavor: ATOM] ~ { oldSelection: Selection _ NARROW[List.Assoc[key: flavor, aList: GlobalSelections]]; GlobalSelections _ List.PutAssoc[key: flavor, val: NIL, aList: GlobalSelections]; IF (oldSelection # NIL) AND (oldSelection.active) THEN PaintEnqueue[oldSelection.viewer]; }; UnSelectViewer: PUBLIC PROC[v: Viewer] ~ { viewer: Viewer _ NIL; displayExpr: DisplayExpr _ NIL; FOR flavors: LIST OF ATOM _ SelectionFlavors, flavors.rest UNTIL flavors = NIL DO [viewer, displayExpr] _ GetSelection[flavors.first ! noSelection => {viewer _ NIL; CONTINUE}]; IF v = viewer THEN UnSelect[flavors.first]; ENDLOOP; }; AddNewFlavor: PROC[flavor: ATOM] ~ { FOR flavors: LIST OF ATOM _ SelectionFlavors, flavors.rest UNTIL flavors = NIL DO IF flavors.first = flavor THEN RETURN; -- already exists in list ENDLOOP; SelectionFlavors _ CONS[flavor, SelectionFlavors]; -- not already in list, so add it }; END. LViewExprOpsImpl.mesa Carl Waldspurger ,August 18, 1986 2:42:11 pm PDT Type Abbreviations From Imported Interfacs Types Global Data (global within this module only) Paint "Queue" Operations modifies: paintQueue effects: If v is not already enqueued, adds v to paintQueue if above loop doesn't return, then we need to add v to queue modifies: paintQueue effects: Removes v from paintQueue. cons up new queue skipping over v make newQueue active modifies: paintQueue effects: Paints each viewer in paintQueue and resets paintQueue (NIL). Selection Operations effects: Returns the viewer and display expression associated with currently active selection of type flavor. SIGNALS noSelection if no such selection exists. effects: Returns TRUE if selection of type flavor is currently active. Otherwise returns FALSE. modifies: GlobalSelections, SelectionFlavors effects: Sets selection flavor to expr in viewer and repaints viewer. If a previous selection existed, its associated viewer is repainted. If expr is unselectable, primary selection is cleared (and viewer repainted). save old selection set new primary selection if expr is selectable modifies: GlobalSelections effects: UnSelects current selection of type flavor. Repaints associated viewer if selection was active. save old selection reset old selection repaint viewer if necessary modifies: GlobalSelections effects: UnSelects all selections associated with viewer v. local declarations modifies: SelectionFlavors effects: SelectionFlavors _ UNION(SelectionFlavors, flavor) Κ˜Jšœ™Jšœ0™0J™codešΟk ˜ Kšœœ ˜Kšœ ˜ Kšœœ˜$K˜K˜ K˜—šΟnœœ˜Jšœ!˜(Jšœ˜J˜Jšž*™*J˜Kšœœ˜$Kšœ œ˜0K˜Kšž™J˜Kšœ œœ˜#šœœœ˜KšœœœΟc)˜@KšœœŸ˜#KšœœŸ˜5KšœœŸ$˜=K˜K˜—K˜Kšž,™,K™Kšœ œœ œŸ(˜KKšžœœŸ˜AKš žœœœœœŸ*˜QK˜K˜K˜Kšž™K™šž œ œ˜(Kšœ™Kšœ<™K˜—K˜šžœ œ œ˜'Kšœ™Kšœ4™4Kšœ<™