TEditDocuments3Impl.mesa
McGregor on August 26, 1982 2:52 pm
Maxwell, January 6, 1983 11:11 am
Plass, April 15, 1983 1:43 pm
Paxton on June 6, 1983 1:58 pm
Russ Atkinson, July 25, 1983 6:47 pm
Doug Wyatt, May 15, 1984 11:33:32 am PDT
DIRECTORY
Booting USING [RegisterProcs, RollbackProc],
Buttons USING [ButtonProc],
InputFocus USING [GetInputFocus, SetInputFocus],
Menus USING [MenuProc, MouseButton],
MessageWindow USING [Append, Blink, Clear],
Process USING [Detach, MsecToTicks, Pause],
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 [Offset, Location, LocNumber, LocWithin, pZone],
ViewerClasses USING [Viewer],
ViewerMenus USING [Restore, Save],
ViewerOps USING [AddProp, EnumProc, FetchProp, PaintViewer],
ViewerTools USING [GetSelectionContents],
VirtualDesktops USING [EnumerateViewers];
TEditDocuments3Impl:
CEDAR PROGRAM
IMPORTS Booting, InputFocus, MessageWindow, Process, Rope, TEditDocument, TEditDocumentPrivate, TEditInput, TEditScrolling, TEditSelection, TextNode, ViewerMenus, ViewerOps, ViewerTools, VirtualDesktops
EXPORTS TEditDocumentPrivate
= BEGIN OPEN TEditDocumentPrivate;
Viewer: TYPE ~ ViewerClasses.Viewer;
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.ROPE ← NIL], parent: Viewer]
RETURNS [BOOL] = {
TEditInput.CloseEvent[];
ForkCall2[proc, parent, ViewerTools.GetSelectionContents[]];
RETURN [FALSE] };
StackBottom2:
PROC [
proc: PROC [parent: Viewer, fileName: Rope.ROPE ← NIL],
parent: Viewer, fileName: Rope.ROPE] = {
proc[parent, fileName ! ABORTED => CONTINUE] };
ForkCall2:
PROC [
proc: PROC [parent: Viewer, fileName: Rope.ROPE ← NIL],
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: Booting.RollbackProc = {
This is called after Rollback to see if any viewers need to be Reset.
Check: ViewerOps.EnumProc
--PROC [v: Viewer] RETURNS [BOOL ← TRUE]-- = {
tdd: TEditDocument.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--
};
VirtualDesktops.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.MenuProc = {
viewer: 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;
[] ← TEditDocument.SpinAndLock[tdd, "Reset"]; -- delay until after other op completes
loc ← TextNode.LocNumber[tdd.lineTable.lines[0].pos];
TEditDocument.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: 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.
ROPE ←
NIL] = {
[] ← DoLoadFile[parent, fileName, FALSE] };
OpenOp: TEditInput.CommandProc = {
RETURN [ForkViewerOp2[OpenIt,viewer]] };
OpenIt:
PROC [parent: Viewer, fileName: Rope.
ROPE ←
NIL] = {
[] ← DoOpenFile[fileName, parent] };
CloseAndOpenOp: TEditInput.CommandProc = {
RETURN [ForkViewerOp2[CloseAndOpenIt,viewer]] };
CloseAndOpenIt:
PROC [parent: Viewer, fileName: Rope.
ROPE ←
NIL] = {
[] ← 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.
ROPE ←
NIL] = {
[] ← DoLoadImplFile[parent, fileName, FALSE] };
OpenImplOp: TEditInput.CommandProc = {
RETURN [ForkViewerOp2[OpenItImpl,viewer]] };
OpenItImpl:
PROC [parent: Viewer, fileName: Rope.
ROPE ←
NIL] = {
[] ← DoOpenImplFile[fileName, parent] };
CloseAndOpenImplOp: TEditInput.CommandProc = {
RETURN [ForkViewerOp2[CloseAndOpenItImpl,viewer]] };
CloseAndOpenItImpl:
PROC [parent: Viewer, fileName: Rope.
ROPE ←
NIL] = {
[] ← 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,
IF shift THEN $PositionIncludingComments ELSE $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[] };
Find:
PUBLIC Menus.MenuProc = { 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.MenuProc = { 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.MenuProc = { 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.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]]};
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....