<> <> <> <> <> DIRECTORY Carets USING [StartCaret], Imager USING [Context], TEditDocument USING [Selection, SelectionId], TEditSelection USING [CannotFindIt, Copy, Create, ExtendSelection, FixupSelection, FixupCaret, MarkSelection, pSel, sSel, fSel, nilSel], ViewerClasses USING [Viewer]; TEditSelection2Impl: CEDAR MONITOR IMPORTS Carets, TEditSelection EXPORTS TEditSelection = BEGIN OPEN TEditDocument, TEditSelection; SelState: TYPE = {up, down}; pSelState, sSelState, fSelState: SelState _ down; pSelUp: Selection _ Create[]; -- copy of pSel from when put it up sSelUp: Selection _ Create[]; -- copy of sSel from when put it up fSelUp: Selection _ Create[]; -- copy of fSel from when put it up caretVisible: BOOL _ FALSE; CaretVisible: PUBLIC ENTRY PROC RETURNS [BOOL] = { ENABLE UNWIND => NULL; RETURN [caretVisible]; }; IsDown: PUBLIC ENTRY PROC [id: SelectionId] RETURNS [BOOL] = { ENABLE UNWIND => NULL; state: SelState = SELECT id FROM primary => pSelState, secondary => sSelState, feedback => fSelState, ENDCASE => ERROR; RETURN [state=down]; }; ForceDown: PUBLIC ENTRY PROC [id: SelectionId] = { ENABLE UNWIND => NULL; SELECT id FROM primary => pSelState _ down; secondary => sSelState _ down; feedback => fSelState _ down; ENDCASE => ERROR; }; ShowSelection: PUBLIC ENTRY PROC [id: SelectionId, self: ViewerClasses.Viewer, context: Imager.Context] = { ENABLE UNWIND => NULL; sel: Selection = SELECT id FROM primary => pSel, secondary => sSel, feedback => fSel, ENDCASE => ERROR; selUp: Selection = SELECT id FROM primary => pSelUp, secondary => sSelUp, feedback => fSelUp, ENDCASE => ERROR; IF sel.viewer # self THEN RETURN; IF sel.start.metricsValid = sel.end.metricsValid THEN TakeSelectionDownI[id, self, context] ELSE IF selUp.viewer=self THEN ExtendSelection[context, self, selUp, sel, id, sel.start.metricsValid] ELSE TakeSelectionDownI[id, self, context]; }; TakeDownForRedisplay: PUBLIC ENTRY PROC [id: SelectionId, self: ViewerClasses.Viewer, context: Imager.Context] = { ENABLE UNWIND => NULL; sel, selUp: Selection; state: SelState; SELECT id FROM primary => { sel _ pSel; state _ pSelState; selUp _ pSelUp }; secondary => { sel _ sSel; state _ sSelState; selUp _ sSelUp }; feedback => { sel _ fSel; state _ fSelState; selUp _ fSelUp }; ENDCASE => ERROR; IF selUp.viewer # self THEN RETURN; IF state=up THEN TakeSelectionDownI[id, self, context]; sel.start.metricsValid _ sel.end.metricsValid _ FALSE; }; FixUpAfterDisplay: PUBLIC ENTRY PROC [id: SelectionId, self: ViewerClasses.Viewer, context: Imager.Context, caret: BOOL] = { ENABLE UNWIND => NULL; sel, selUp: Selection; state: SelState; SELECT id FROM primary => { sel _ pSel; state _ pSelState; selUp _ pSelUp }; secondary => { sel _ sSel; state _ sSelState; selUp _ sSelUp }; feedback => { sel _ fSel; state _ fSelState; selUp _ fSelUp }; ENDCASE => ERROR; IF sel.viewer # self THEN RETURN; FixupSelection[sel, self, ~sel.start.metricsValid, ~sel.end.metricsValid ! TEditSelection.CannotFindIt => { Copy[source: nilSel, dest: sel]; CONTINUE; } ]; PutSelectionUpI[id, self, context]; IF caret AND sel.viewer=self THEN { FixupCaret[sel]; IF id=primary THEN caretVisible _ (sel.caretY # LAST[INTEGER]); -- remember if visible Carets.StartCaret[self, sel.caretX, sel.caretY, IF id=primary THEN primary ELSE secondary]; }; }; AdjustSelStates: PUBLIC ENTRY PROC [self: ViewerClasses.Viewer] = { ENABLE UNWIND => NULL; IF pSelState=up AND pSelUp.viewer=self THEN pSelState _ down; IF sSelState=up AND sSelUp.viewer=self THEN sSelState _ down; IF fSelState=up AND fSelUp.viewer=self THEN fSelState _ down; }; TakeSelectionDown: PUBLIC ENTRY PROC [id: SelectionId, self: ViewerClasses.Viewer, context: Imager.Context] = { ENABLE UNWIND => NULL; TakeSelectionDownI[id, self, context]; }; TakeSelectionDownI: PROC [id: SelectionId, self: ViewerClasses.Viewer, context: Imager.Context] = { sel: Selection = SELECT id FROM primary => pSelUp, secondary => sSelUp, feedback => fSelUp, ENDCASE => ERROR; state: SelState = SELECT id FROM primary => pSelState, secondary => sSelState, feedback => fSelState, ENDCASE => ERROR; IF sel.viewer # self OR state=down THEN RETURN; IF sel.granularity#point AND state=up THEN MarkSelection[context, self, sel, id]; SELECT id FROM primary => pSelState _ down; secondary => sSelState _ down; feedback => fSelState _ down; ENDCASE => ERROR; }; PutSelectionUp: PUBLIC ENTRY PROC [id: SelectionId, self: ViewerClasses.Viewer, context: Imager.Context] = { ENABLE UNWIND => NULL; PutSelectionUpI[id, self, context]; }; PutSelectionUpI: PROC [id: SelectionId, self: ViewerClasses.Viewer, context: Imager.Context] = { sel, selUp: Selection; state: SelState; SELECT id FROM primary => { sel _ pSel; state _ pSelState; selUp _ pSelUp }; secondary => { sel _ sSel; state _ sSelState; selUp _ sSelUp }; feedback => { sel _ fSel; state _ fSelState; selUp _ fSelUp }; ENDCASE => ERROR; IF sel.viewer # self OR state=up THEN RETURN; -- something went wrong Copy[source: sel, dest: selUp]; IF sel.granularity#point AND state=down THEN MarkSelection[context, self, selUp, id]; SELECT id FROM primary => pSelState _ up; secondary => sSelState _ up; feedback => fSelState _ up; ENDCASE => ERROR; }; END.