TEditDocuments3Impl.mesa
Copyright Ó 1985, 1987, 1988, 1989, 1990, 1991, 1992 by Xerox Corporation. All rights reserved.
Russ Atkinson (RRA) August 19, 1985 4:05:04 pm PDT
Michael Plass, March 23, 1989 2:32:33 pm PST
Doug Wyatt, October 18, 1991 12:08 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, 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],
ViewerOps USING [AddProp, FetchProp, PaintViewer, SaveViewer],
ViewerTools USING [GetSelectionContents];
TEditDocuments3Impl: CEDAR PROGRAM
IMPORTS InputFocus, MessageWindow, Process, Rope, TEditDocument, TEditDocumentPrivate, TEditInput, TEditScrolling, TEditSelection, TextNode, ViewerForkers, ViewerGroupLocks, ViewerOps, ViewerTools
EXPORTS TEditDocumentPrivate
=
BEGIN
OPEN TEditDocumentPrivate;
ROPE: TYPE ~ Rope.ROPE;
Viewer: TYPE ~ ViewerClasses.Viewer;
Do:
PROC [viewer:
REF
ANY, atom:
ATOM] =
INLINE
--gfi saver-- {
TEditInput.InterpretAtom[NARROW[viewer], atom];
};
Register:
PROC [atom:
ATOM, op: TEditInput.CommandProc] =
INLINE
--gfi saver-- {
TEditInput.Register[atom, op];
};
ForkViewerOp2:
PROC [proc:
PROC [parent: Viewer, fileName:
ROPE ¬
NIL], parent: Viewer]
RETURNS [
BOOL] = {
TEditInput.CloseEvent[];
ViewerForkers.ForkCall[parent, StackBase, NEW[Data2 ¬ [proc, parent, ViewerTools.GetSelectionContents[]]]];
RETURN [FALSE]
};
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];
ViewerOps.RestoreViewer[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] =
INLINE
--gfi saver-- {
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]];
};
SaveViewer:
PROC [viewer: Viewer] = { [] ¬ ViewerOps.SaveViewer[viewer] };
SaveOp: TEditInput.CommandProc = {
TEditInput.CloseEvent[];
IF
NOT viewer.saveInProgress
AND (viewer.newFile
OR viewer.newVersion)
THEN {
[] ¬ Process.Detach[FORK SaveViewer[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 = {
IF viewer.newVersion
THEN {
MessageWindow.Append["Clear would lose edits.", TRUE];
MessageWindow.Blink[];
}
ELSE {
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: fileName, column: IF parent # NIL THEN parent.column ELSE left, parent: 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: fileName, column: IF parent # NIL THEN parent.column ELSE left, parent: 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,
SELECT mouseButton
FROM
red => IF shift THEN $PositionIncludingComments ELSE $Position,
yellow => IF shift THEN $MsgPositionIncludingComments ELSE $MsgPosition,
blue => IF shift THEN $StuffPositionIncludingComments ELSE $StuffPosition,
ENDCASE => ERROR
];
};
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.