TEditDocuments3Impl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Plass, March 29, 1985 3:36:43 pm PST
Doug Wyatt, April 5, 1985 5:49:28 pm PST
Russ Atkinson (RRA) August 19, 1985 4:05:04 pm PDT
DIRECTORY
Booting USING [RegisterProcs, RollbackProc],
Buttons USING [ButtonProc],
InputFocus USING [GetInputFocus, SetInputFocus],
Menus USING [ClickProc, MouseButton],
MessageWindow USING [Append, Blink, Clear],
Process USING [Detach],
Rope USING [Concat, ROPE],
TEditDocument USING [Selection, SpinAndLock, TEditDocumentData, Unlock],
TEditDocumentPrivate USING [AnonymousLoadFile, AnonymousLoadImplFile, CloseAndNewViewer, CloseAndOpenPreviousFile, DoCloseAndOpenFile, DoCloseAndOpenImplFile, DoLoadFile, DoLoadImplFile, DoOpenFile, DoOpenImplFile, DoStoreFile, EmptyViewer, FileIsMoreRecent, LoadPreviousFile, NewViewer, OpenPreviousFile, PositionHistory, PositionViewer, PreLoadPrevious],
TEditInput USING [CheckSelection, CloseEvent, CommandProc, InterpretAtom, Register],
TEditScrolling USING [AutoScroll],
TEditSelection USING [MakeSelection],
TextNode USING [Location, LocNumber, LocWithin],
ViewerClasses USING [Viewer],
ViewerForkers USING [CallBack, ForkCall],
ViewerGroupLocks USING [CallRootAndLinksUnderWriteLock],
ViewerMenus USING [Restore, Save],
ViewerOps USING [AddProp, EnumerateViewers, EnumProc, FetchProp, PaintViewer],
ViewerTools USING [GetSelectionContents];
TEditDocuments3Impl:
CEDAR
PROGRAM
IMPORTS Booting, InputFocus, MessageWindow, Process, Rope, TEditDocument, TEditDocumentPrivate, TEditInput, TEditScrolling, TEditSelection, TextNode, ViewerForkers, ViewerGroupLocks, ViewerMenus, ViewerOps, ViewerTools
EXPORTS TEditDocumentPrivate
= BEGIN OPEN TEditDocumentPrivate;
ROPE: TYPE ~ Rope.ROPE;
Viewer: TYPE ~ ViewerClasses.Viewer;
Do:
PROC [viewer:
REF
ANY, atom:
ATOM] = {
TEditInput.InterpretAtom[NARROW[viewer], atom];
};
Register:
PROC [atom:
ATOM, op: TEditInput.CommandProc] = {
TEditInput.Register[atom, op];
};
ForkViewerOp2:
PROC [proc:
PROC [parent: Viewer, fileName:
ROPE ←
NIL], parent: Viewer]
RETURNS [
BOOL ←
FALSE] = {
TEditInput.CloseEvent[];
ViewerForkers.ForkCall[parent, StackBase, NEW[Data2 ← [proc, parent, ViewerTools.GetSelectionContents[]]]];
};
ForkViewerOp:
PROC [proc:
PROC [parent: Viewer], parent: Viewer]
RETURNS [
BOOL ←
FALSE] = {
TEditInput.CloseEvent[];
ViewerForkers.ForkCall[parent, StackBase, NEW[Data1 ← [proc, parent]]];
};
Data1:
TYPE =
RECORD [
proc: PROC [parent: Viewer],
viewer: Viewer];
Data2:
TYPE =
RECORD [
proc: PROC [parent: Viewer, fileName: ROPE],
viewer: Viewer,
fileName: ROPE];
StackBase: ViewerForkers.CallBack = {
[data: REF ANY]
WITH data
SELECT
FROM
data1:
REF Data1 => {
data1.proc[data1.viewer ! ABORTED => CONTINUE];
};
data2:
REF Data2 => {
data2.proc[data2.viewer, data2.fileName ! ABORTED => CONTINUE];
};
ENDCASE;
};
CheckFilesAfterRollback: Booting.RollbackProc = {
This is called after Rollback to see if any viewers need to be Reset.
Check: ViewerOps.EnumProc = {
[v: ViewerClasses.Viewer] RETURNS [BOOL ← TRUE]
WITH v.data
SELECT
FROM
tdd: TEditDocument.TEditDocumentData => {
IF FileIsMoreRecent[tdd.text, v.file]
THEN {
MessageWindow.Append[Rope.Concat["Loading newer version of ", v.file], TRUE];
ViewerMenus.Restore[v]; -- reload the file
};
};
ENDCASE;
RETURN [TRUE] --continue enumeration--
};
ViewerOps.EnumerateViewers[Check]; -- Check each top level viewer
};
Reset
SelectMouse:
PROC [mouseButton: Menus.MouseButton, redOp, yellowOp, blueOp:
ATOM]
RETURNS [
ATOM] = {
RETURN [
SELECT mouseButton
FROM
red => redOp, yellow => yellowOp, blue => blueOp,
ENDCASE => ERROR];
PreReset:
PUBLIC Menus.ClickProc = {
WITH parent
SELECT
FROM
viewer: Viewer =>
MessageWindow.Append[
IF viewer.file = NIL THEN "Confirm clearing viewer" ELSE Rope.Concat["Confirm reloading of ", viewer.file],
TRUE];
ENDCASE;
};
Reset:
PUBLIC Menus.ClickProc = {
MessageWindow.Clear[];
Do[parent, SelectMouse[mouseButton, $RedReset, $YellowReset, $BlueReset]];
};
ResetOp: TEditInput.CommandProc = {
[viewer: ViewerClasses.Viewer ← NIL] RETURNS [recordAtom: BOOL ← TRUE, quit: BOOL ← FALSE]
inner:
PROC = {
FOR v: Viewer ← viewer, v.link
UNTIL v =
NIL
DO
WITH v.data
SELECT
FROM
tdd: TEditDocument.TEditDocumentData => {
[] ← TEditDocument.SpinAndLock[tdd, "Reset"];
ViewerOps.AddProp[v, $ResetLoc, NEW[INT ← TextNode.LocNumber[tdd.lineTable.lines[0].pos]]];
v.newVersion ← TRUE; -- to force the init proc to reread the file
TEditDocument.Unlock[tdd];
};
ENDCASE;
IF v.link=viewer THEN EXIT;
ENDLOOP;
FOR v: Viewer ← viewer, v.link
UNTIL v =
NIL
DO
WITH v.data
SELECT
FROM
tdd: TEditDocument.TEditDocumentData => {
IF InputFocus.GetInputFocus[].owner=v THEN InputFocus.SetInputFocus[];
WITH ViewerOps.FetchProp[v, $ResetLoc]
SELECT
FROM
locRef:
REF
INT => {
v.class.init[v];
v.newVersion ← v.newFile ← FALSE;
[] ← TEditDocument.SpinAndLock[tdd, "Reset"];
IF ~PositionViewer[v,TextNode.LocWithin[tdd.text,locRef^],all]
THEN
ViewerOps.PaintViewer[v, all];
TEditDocument.Unlock[tdd];
};
ENDCASE;
};
ENDCASE;
IF v.link=viewer THEN EXIT;
ENDLOOP;
};
ViewerGroupLocks.CallRootAndLinksUnderWriteLock[inner, viewer];
};
Save
Save:
PUBLIC Menus.ClickProc = {
MessageWindow.Clear[];
Do[parent, SelectMouse[mouseButton, $RedSave, $YellowSave, $BlueSave]];
};
SaveOp: TEditInput.CommandProc = {
TEditInput.CloseEvent[];
IF ~viewer.saveInProgress
THEN
TRUSTED {
[] ← Process.Detach[FORK ViewerMenus.Save[viewer]];
};
RETURN [FALSE];
};
Clear = Empty, New, or CloseAndNew
PreClear:
PUBLIC Menus.ClickProc = {
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.ClickProc = {
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.ClickProc = {
MessageWindow.Clear[];
Do[parent, SelectMouse[mouseButton, $RedStore, $YellowStore, $BlueStore]];
};
StoreOp: TEditInput.CommandProc = {
RETURN [ForkViewerOp2[DoStoreFile,viewer]] };
PreviousFile = LoadPrevious, OpenPrevious, or CloseAndOpenPrevious
PreviousFile:
PUBLIC Menus.ClickProc = {
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.ClickProc = {
Do[parent,$AnonymousLoadImpl];
};
AnonymousLoadImplOp: TEditInput.CommandProc = {
RETURN [ForkViewerOp[AnonymousLoadImplFile,viewer]];
};
AnonymousLoad:
PUBLIC Menus.ClickProc = {
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.ClickProc = {
viewer: Viewer = NARROW[parent];
MessageWindow.Append["Click LEFT to load in this viewer, MIDDLE for new viewer, RIGHT for close & new", TRUE];
};
Get:
PUBLIC Menus.ClickProc = {
PreGet[parent];
Do[parent, SelectMouse[mouseButton, $Load, $Open, $CloseAndOpen]];
};
LoadOp: TEditInput.CommandProc = {
RETURN [ForkViewerOp2[LoadIt,viewer]] };
LoadIt:
PROC [parent: Viewer, fileName:
ROPE ←
NIL] = {
[] ← DoLoadFile[parent, fileName, FALSE];
};
OpenOp: TEditInput.CommandProc = {
RETURN [ForkViewerOp2[OpenIt,viewer]];
};
OpenIt:
PROC [parent: Viewer, fileName:
ROPE ←
NIL] = {
[] ← DoOpenFile[fileName, parent];
};
CloseAndOpenOp: TEditInput.CommandProc = {
RETURN [ForkViewerOp2[CloseAndOpenIt,viewer]];
};
CloseAndOpenIt:
PROC [parent: Viewer, fileName:
ROPE ←
NIL] = {
[] ← DoCloseAndOpenFile[parent, fileName];
};
GetImpl = LoadImpl, OpenImpl, or CloseAndOpenImpl
GetImpl:
PUBLIC Menus.ClickProc = {
PreGetImpl[parent];
Do[parent, SelectMouse[mouseButton, $LoadImpl, $OpenImpl, $CloseAndOpenImpl]];
};
LoadImplOp: TEditInput.CommandProc = {
RETURN [ForkViewerOp2[LoadItImpl,viewer]];
};
LoadItImpl:
PROC [parent: Viewer, fileName:
ROPE ←
NIL] = {
[] ← DoLoadImplFile[parent, fileName, FALSE];
};
OpenImplOp: TEditInput.CommandProc = {
RETURN [ForkViewerOp2[OpenItImpl,viewer]];
};
OpenItImpl:
PROC [parent: Viewer, fileName:
ROPE ←
NIL] = {
[] ← DoOpenImplFile[fileName, parent];
};
CloseAndOpenImplOp: TEditInput.CommandProc = {
RETURN [ForkViewerOp2[CloseAndOpenItImpl,viewer]];
};
CloseAndOpenItImpl:
PROC [parent: Viewer, fileName:
ROPE ←
NIL] = {
[] ← DoCloseAndOpenImplFile[parent, fileName];
};
OpenButton:
PUBLIC Buttons.ButtonProc = {
This is the Open button in the upper right corner of the screen.
[] ← ForkViewerOp2[OpenIt, NIL];
};
Places menu commands
Normalize:
PUBLIC Menus.ClickProc = {
Do[parent, SelectMouse[mouseButton, $NormalizeToStart, $NormalizeToCaret, $NormalizeToEnd]];
};
Position:
PUBLIC Menus.ClickProc = {Do[parent,
IF shift THEN $PositionIncludingComments ELSE $Position];
};
JumpToPrevious: PUBLIC Menus.ClickProc = {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.ClickProc = {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];
Find:
PUBLIC Menus.ClickProc = { Do[parent,
SELECT mouseButton
FROM
red => IF shift THEN $FindNextCaseless ELSE $FindNext,
yellow => IF shift THEN $FindAnyCaseless ELSE $FindAny,
blue => IF shift THEN $FindPrevCaseless ELSE $FindPrev,
ENDCASE => ERROR];
};
FindDef:
PUBLIC Menus.ClickProc = { Do[parent,
SELECT mouseButton
FROM
red => IF shift THEN $FindNextDefCaseless ELSE $FindNextDef,
yellow => IF shift THEN $FindAnyDefCaseless ELSE $FindAnyDef,
blue => IF shift THEN $FindPrevDefCaseless ELSE $FindPrevDef,
ENDCASE => ERROR];
};
FindWord:
PUBLIC Menus.ClickProc = { Do[parent,
SELECT mouseButton
FROM
red => IF shift THEN $FindNextWordCaseless ELSE $FindNextWord,
yellow => IF shift THEN $FindAnyWordCaseless ELSE $FindAnyWord,
blue => IF shift THEN $FindPrevWordCaseless ELSE $FindPrevWord,
ENDCASE => ERROR];
};
Levels menu commands
FewerLevels: PUBLIC Menus.ClickProc = {Do[parent,$FewerLevels]};
MoreLevels: PUBLIC Menus.ClickProc = {Do[parent,$MoreLevels]};
AllLevels: PUBLIC Menus.ClickProc = {Do[parent,$AllLevels]};
FirstLevelOnly: PUBLIC Menus.ClickProc = {Do[parent,$FirstLevelOnly]};
Lines menu commands
FewerLines: PUBLIC Menus.ClickProc = {Do[parent,$FewerLines]};
MoreLines: PUBLIC Menus.ClickProc = {Do[parent,$MoreLines]};
AllLines: PUBLIC Menus.ClickProc = {Do[parent,$AllLines]};
FirstLineOnly: PUBLIC Menus.ClickProc = {Do[parent,$FirstLineOnly]};
Time
Time: PUBLIC Menus.ClickProc = {Do[parent,$Time]};
Split
Split:
PUBLIC Menus.ClickProc = {Do[parent,
SelectMouse[mouseButton, $RedSplit, $YellowSplit, $BlueSplit]];
};
Booting.RegisterProcs[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.