-- TEditDocuments3Impl.mesa; Edited by Paxton on June 6, 1983 1:58 pm
-- Edited by McGregor on August 26, 1982 2:52 pm
Last Edited by: Maxwell, January 6, 1983 11:11 am
Last Edited by: Plass, April 15, 1983 1:43 pm
DIRECTORY
Buttons USING [ButtonProc],
CedarSnapshot USING [After, Register],
InputFocus USING [GetInputFocus, SetInputFocus],
Menus USING [MenuProc, MouseButton],
MessageWindow USING [Append, Blink, Clear],
Process USING [Detach, MsecToTicks, Pause],
Rope USING [Concat, ROPE],
TEditDocument,
TEditDocumentPrivate,
TEditInput USING [CheckSelection, CloseEvent, CommandProc, InterpretAtom, Register],
TEditOps,
TEditScrolling USING [AutoScroll],
TEditSelection USING [MakeSelection],
TextNode USING [Offset, Location, LocNumber, LocWithin, pZone],
ViewerMenus USING [Restore, Save],
ViewerClasses USING [Viewer, ViewerClass],
ViewerTools USING [GetSelectionContents],
ViewerOps USING [AddProp, EnumProc, FetchProp, PaintViewer],
VirtualDesktops USING [EnumerateViewers];
TEditDocuments3Impl: CEDAR PROGRAM
IMPORTS CedarSnapshot, InputFocus, MessageWindow, Process, Rope, TEditDocument, TEditDocumentPrivate, TEditInput, TEditScrolling, TEditSelection, TextNode, ViewerMenus, ViewerOps, ViewerTools, VirtualDesktops
EXPORTS TEditDocumentPrivate =
BEGIN OPEN TEditDocument, TEditDocumentPrivate, ViewerClasses;
Do: PROC [viewer: REF ANY, atom: ATOM] = INLINE {
TEditInput.InterpretAtom[NARROW[viewer], atom] };
Register: PROC [atom: ATOM, op: TEditInput.CommandProc] = { TEditInput.Register[atom, op] };
ForkViewerOp2: PROC [
proc: PROC [parent: Viewer, fileName: Rope.ROPENIL], parent: Viewer]
RETURNS [BOOL] = {
TEditInput.CloseEvent[];
ForkCall2[proc, parent, ViewerTools.GetSelectionContents[]];
RETURN [FALSE] };
StackBottom2: PROC [
proc: PROC [parent: Viewer, fileName: Rope.ROPENIL],
parent: Viewer, fileName: Rope.ROPE] = {
proc[parent, fileName ! ABORTED => CONTINUE] };
ForkCall2: PROC [
proc: PROC [parent: Viewer, fileName: Rope.ROPENIL],
parent: Viewer, fileName: Rope.ROPE] = {
TRUSTED {Process.Detach[FORK StackBottom2[proc, parent, fileName]]};
Process.Pause[Process.MsecToTicks[250]];
};
ForkViewerOp: PROC [proc: PROC [parent: Viewer], parent: Viewer] RETURNS [BOOL] = {
TEditInput.CloseEvent[];
ForkCall[proc, parent];
RETURN [FALSE] };
StackBottom: PROC [proc: PROC [parent: Viewer], parent: Viewer] = {
proc[parent ! ABORTED => CONTINUE] };
ForkCall: PROC [proc: PROC [parent: Viewer], parent: Viewer] = {
TRUSTED {Process.Detach[FORK StackBottom[proc, parent]]};
-- fork so can release input monitor without waiting for call to complete
Process.Pause[Process.MsecToTicks[250]];
-- HACK: wait 1/4 sec to let other process lock the tdd before we return
};
CheckFilesAfterRollback: PROC [when: CedarSnapshot.After] = {
This is called after Rollback to see if any viewers need to be Reset.
Check: ViewerOps.EnumProc --PROC [v: Viewer] RETURNS [BOOL ← TRUE]-- = {
tdd: TEditDocumentData;
IF v.class.flavor # $Text THEN RETURN [TRUE]; -- only interested in text viewers
tdd ← NARROW[v.data];
IF tdd = NIL THEN RETURN [TRUE];
IF ~FileIsMoreRecent[tdd.text, v.file] THEN RETURN [TRUE];
MessageWindow.Append[Rope.Concat["Loading newer version of ", v.file], TRUE];
ViewerMenus.Restore[v]; -- reload the file
RETURN [TRUE] --continue enumeration-- };
IF when=checkpoint THEN RETURN; -- only do this after return from Rollback
VirtualDesktops.EnumerateViewers[Check]; -- Check each top level viewer
};
Reset
PreReset: PUBLIC Menus.MenuProc = {
viewer: ViewerClasses.Viewer = NARROW[parent];
IF viewer.file = NIL THEN MessageWindow.Append["Confirm clearing viewer", TRUE]
ELSE MessageWindow.Append[Rope.Concat["Confirm reloading of ", viewer.file], TRUE] };
Reset: PUBLIC Menus.MenuProc = {
MessageWindow.Clear[];
Do[parent, SelectMouse[mouseButton, $RedReset, $YellowReset, $BlueReset]] };
ResetOp: TEditInput.CommandProc = {
SaveLoc: PROC [v: Viewer] = BEGIN
tdd: TEditDocument.TEditDocumentData ← NARROW[v.data];
loc: INT;
IF tdd = NIL THEN RETURN;
[] ← SpinAndLock[tdd, "Reset"]; -- delay until after other op completes
loc ← TextNode.LocNumber[tdd.lineTable.lines[0].pos];
Unlock[tdd];
ViewerOps.AddProp[v, $ResetLoc, TextNode.pZone.NEW[INT ← loc]];
v.newVersion ← TRUE; -- to force the init proc to reread the file
END;
DoOne: PROC [v: Viewer] = BEGIN
tdd: TEditDocument.TEditDocumentData ← NARROW[v.data];
locRef: REF INT;
IF tdd = NIL THEN RETURN;
IF InputFocus.GetInputFocus[].owner=v THEN InputFocus.SetInputFocus[];
locRef ← NARROW[ViewerOps.FetchProp[v, $ResetLoc]];
v.class.init[v];
v.newVersion ← v.newFile ← FALSE;
IF locRef = NIL OR ~PositionViewer[v,TextNode.LocWithin[tdd.text,locRef^],all] THEN
ViewerOps.PaintViewer[v, all];
END;
SaveLoc[viewer];
IF viewer.link#NIL THEN
FOR v: Viewer ← viewer.link, v.link UNTIL v=viewer DO SaveLoc[v]; ENDLOOP;
DoOne[viewer];
IF viewer.link#NIL THEN
FOR v: Viewer ← viewer.link, v.link UNTIL v=viewer DO DoOne[v]; ENDLOOP;
RETURN [FALSE] };
Save
Save: PUBLIC Menus.MenuProc = {
MessageWindow.Clear[];
Do[parent, SelectMouse[mouseButton, $RedSave, $YellowSave, $BlueSave]] };
SaveOp: TEditInput.CommandProc = BEGIN
TEditInput.CloseEvent[];
IF ~viewer.saveInProgress THEN
TRUSTED {[] ← Process.Detach[FORK ViewerMenus.Save[viewer]]};
RETURN [FALSE];
END;
Clear = Empty, New, or CloseAndNew
PreClear: PUBLIC Menus.MenuProc = { -- called when Clear menu item becomes unguarded
MessageWindow.Append[clearFirst: TRUE, message:
"Click LEFT to empty this viewer, MIDDLE to make new viewer, RIGHT for close & new"] };
Clear: PUBLIC Menus.MenuProc = {
--PreClear[parent];
Do[parent, SelectMouse[mouseButton, $Empty, $New, $CloseAndNew]]};
Don't fork these operations since they change the selection; want to capture typein that follows calls on these.
EmptyOp: TEditInput.CommandProc = { EmptyViewer[viewer]; RETURN [FALSE] };
NewOp: TEditInput.CommandProc = { NewViewer[viewer]; RETURN [FALSE] };
NewButton: PUBLIC Buttons.ButtonProc = { NewViewer[NIL] };
This is the button in the upper left corner.
CloseAndNewOp: TEditInput.CommandProc = {
CloseAndNewViewer[viewer]; RETURN [FALSE] };
Store
Store: PUBLIC Menus.MenuProc = {
MessageWindow.Clear[];
Do[parent, SelectMouse[mouseButton, $RedStore, $YellowStore, $BlueStore]] };
StoreOp: TEditInput.CommandProc = { RETURN [ForkViewerOp2[DoStoreFile,viewer]] };
PreviousFile = LoadPrevious, OpenPrevious, or CloseAndOpenPrevious
PreviousFile: PUBLIC Menus.MenuProc = {
PreLoadPrevious[parent];
Do[parent, SelectMouse[mouseButton, $LoadPrevious, $OpenPrevious, $CloseAndOpenPrevious]]};
LoadPreviousOp: TEditInput.CommandProc = {
RETURN [ForkViewerOp[LoadPreviousFile,viewer]] };
OpenPreviousOp: TEditInput.CommandProc = {
RETURN [ForkViewerOp[OpenPreviousFile,viewer]] };
CloseAndOpenPreviousOp: TEditInput.CommandProc = {
RETURN [ForkViewerOp[CloseAndOpenPreviousFile,viewer]] };
Anonymous Loads -- into NoName viewers
AnonymousLoadImpl: PUBLIC Menus.MenuProc = { Do[parent,$AnonymousLoadImpl] };
AnonymousLoadImplOp: TEditInput.CommandProc = {
RETURN [ForkViewerOp[AnonymousLoadImplFile,viewer]] };
AnonymousLoad: PUBLIC Menus.MenuProc = { Do[parent,$AnonymousLoad] };
AnonymousLoadOp: TEditInput.CommandProc = {
RETURN [ForkViewerOp[AnonymousLoadIt,viewer]] };
AnonymousLoadIt: PROC [parent: Viewer] = { AnonymousLoadFile[parent] };
Get = Load, Open, or CloseAndOpen
PreGet, PreGetImpl: PUBLIC Menus.MenuProc = {
viewer: ViewerClasses.Viewer = NARROW[parent];
MessageWindow.Append[
"Click LEFT to load in this viewer, MIDDLE for new viewer, RIGHT for close & new", TRUE] };
Get: PUBLIC Menus.MenuProc = {
--PreGet[parent];
Do[parent, SelectMouse[mouseButton, $Load, $Open, $CloseAndOpen]]};
LoadOp: TEditInput.CommandProc = { RETURN [ForkViewerOp2[LoadIt,viewer]] };
LoadIt: PROC [parent: Viewer, fileName: Rope.ROPENIL] = {
[] ← DoLoadFile[parent, fileName, FALSE] };
OpenOp: TEditInput.CommandProc = { RETURN [ForkViewerOp2[OpenIt,viewer]] };
OpenIt: PROC [parent: Viewer, fileName: Rope.ROPENIL] = {
[] ← DoOpenFile[fileName, parent] };
CloseAndOpenOp: TEditInput.CommandProc = {
RETURN [ForkViewerOp2[CloseAndOpenIt,viewer]] };
CloseAndOpenIt: PROC [parent: Viewer, fileName: Rope.ROPENIL] = {
[] ← DoCloseAndOpenFile[parent, fileName] };
GetImpl = LoadImpl, OpenImpl, or CloseAndOpenImpl
GetImpl: PUBLIC Menus.MenuProc = {
--PreGetImpl[parent];
Do[parent, SelectMouse[mouseButton, $LoadImpl, $OpenImpl, $CloseAndOpenImpl]]};
LoadImplOp: TEditInput.CommandProc = {
RETURN [ForkViewerOp2[LoadItImpl,viewer]] };
LoadItImpl: PROC [parent: Viewer, fileName: Rope.ROPENIL] = {
[] ← DoLoadImplFile[parent, fileName, FALSE] };
OpenImplOp: TEditInput.CommandProc = {
RETURN [ForkViewerOp2[OpenItImpl,viewer]] };
OpenItImpl: PROC [parent: Viewer, fileName: Rope.ROPENIL] = {
[] ← DoOpenImplFile[fileName, parent] };
CloseAndOpenImplOp: TEditInput.CommandProc = {
RETURN [ForkViewerOp2[CloseAndOpenItImpl,viewer]] };
CloseAndOpenItImpl: PROC [parent: Viewer, fileName: Rope.ROPENIL] = {
[] ← DoCloseAndOpenImplFile[parent, fileName] };
OpenButton: PUBLIC Buttons.ButtonProc = { [] ← ForkViewerOp2[OpenIt,NIL] };
This is the Open button in the upper left corner of the screen.
Places menu commands
Normalize: PUBLIC Menus.MenuProc = {
Do[parent, SelectMouse[mouseButton, $NormalizeToStart, $NormalizeToCaret, $NormalizeToEnd]]};
Position: PUBLIC Menus.MenuProc = {Do[parent,$Position]};
JumpToPrevious: PUBLIC Menus.MenuProc = {Do[parent,$PrevPlace]};
PrevPlaceOp: TEditInput.CommandProc = {
tdd: TEditDocument.TEditDocumentData ← NARROW[viewer.data];
prop: REF PositionHistory ← NARROW[ViewerOps.FetchProp[viewer, $PositionHistory]];
IF tdd # NIL AND prop # NIL THEN {
loc: TextNode.Location ← prop.pos;
IF loc = tdd.lineTable.lines[0].pos THEN loc ← prop.prev;
IF PositionViewer[viewer, loc] THEN RETURN;
IF loc # prop.prev AND PositionViewer[viewer, prop.prev] THEN RETURN };
MessageWindow.Append["No previous place saved.", TRUE];
MessageWindow.Blink[];
RETURN [FALSE] };
Reselect: PUBLIC Menus.MenuProc = {Do[parent,$Reselect]};
ReselectOp: TEditInput.CommandProc = {
tdd: TEditDocument.TEditDocumentData ← NARROW[viewer.data];
prop: TEditDocument.Selection ← NARROW[ViewerOps.FetchProp[viewer, $SelectionHistory]];
IF tdd # NIL AND prop # NIL AND TEditInput.CheckSelection[prop] THEN {
TEditSelection.MakeSelection[selection: primary, new: prop];
TEditScrolling.AutoScroll[viewer,FALSE] }
ELSE {
MessageWindow.Append["No saved selection.", TRUE];
MessageWindow.Blink[] };
RETURN [FALSE] };
SelectMouse: PROC [mouseButton: Menus.MouseButton, redOp, yellowOp, blueOp: ATOM]
RETURNS [ATOM] = {
RETURN [SELECT mouseButton FROM
red => redOp, yellow => yellowOp, blue => blueOp,
ENDCASE => ERROR] };
Find: PUBLIC Menus.MenuProc = {
Do[parent, SelectMouse[mouseButton, $FindNext, $FindAny, $FindPrev]]};
FindDef: PUBLIC Menus.MenuProc = {
Do[parent, SelectMouse[mouseButton, $FindNextDef, $FindAnyDef, $FindPrevDef]]};
FindWord: PUBLIC Menus.MenuProc = {
Do[parent, SelectMouse[mouseButton, $FindNextWord, $FindAnyWord, $FindPrevWord]]};
Levels menu commands
FewerLevels: PUBLIC Menus.MenuProc = {Do[parent,$FewerLevels]};
MoreLevels: PUBLIC Menus.MenuProc = {Do[parent,$MoreLevels]};
AllLevels: PUBLIC Menus.MenuProc = {Do[parent,$AllLevels]};
FirstLevelOnly: PUBLIC Menus.MenuProc = {Do[parent,$FirstLevelOnly]};
Lines menu commands
FewerLines: PUBLIC Menus.MenuProc = {Do[parent,$FewerLines]};
MoreLines: PUBLIC Menus.MenuProc = {Do[parent,$MoreLines]};
AllLines: PUBLIC Menus.MenuProc = {Do[parent,$AllLines]};
FirstLineOnly: PUBLIC Menus.MenuProc = {Do[parent,$FirstLineOnly]};
Time
Time: PUBLIC Menus.MenuProc = {Do[parent,$Time]};
Split
Split: PUBLIC Menus.MenuProc = {Do[parent,
SelectMouse[mouseButton, $RedSplit, $YellowSplit, $BlueSplit]]};
TRUSTED {CedarSnapshot.Register[r: CheckFilesAfterRollback]};
Register[$RedReset,ResetOp]; Register[$YellowReset,ResetOp]; Register[$BlueReset,ResetOp];
Register[$RedSave,SaveOp]; Register[$YellowSave,SaveOp]; Register[$BlueSave,SaveOp];
Register[$Empty,EmptyOp];
Register[$New,NewOp];
Register[$CloseAndNew,CloseAndNewOp];
Register[$RedStore, StoreOp]; Register[$YellowStore, StoreOp]; Register[$BlueStore, StoreOp];
Register[$LoadPrevious,LoadPreviousOp];
Register[$OpenPrevious,OpenPreviousOp];
Register[$CloseAndOpenPrevious,CloseAndOpenPreviousOp];
Register[$AnonymousLoadImpl,AnonymousLoadImplOp];
Register[$AnonymousLoad,AnonymousLoadOp];
Register[$Load,LoadOp];
Register[$Open,OpenOp];
Register[$CloseAndOpen,CloseAndOpenOp];
Register[$LoadImpl,LoadImplOp];
Register[$OpenImpl,OpenImplOp];
Register[$CloseAndOpenImpl,CloseAndOpenImplOp];
Register[$PrevPlace,PrevPlaceOp];
Register[$Reselect,ReselectOp];
END....