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.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]]}; Process.Pause[Process.MsecToTicks[250]]; }; CheckFilesAfterRollback: PROC [--when: CedarSnapshot.After--] = { 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 }; 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: 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; 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]]}; EmptyOp: TEditInput.CommandProc = { EmptyViewer[viewer]; RETURN [FALSE] }; NewOp: TEditInput.CommandProc = { NewViewer[viewer]; RETURN [FALSE] }; NewButton: PUBLIC Buttons.ButtonProc = { NewViewer[NIL] }; CloseAndNewOp: TEditInput.CommandProc = { CloseAndNewViewer[viewer]; RETURN [FALSE] }; Store: PUBLIC Menus.MenuProc = { MessageWindow.Clear[]; Do[parent, SelectMouse[mouseButton, $RedStore, $YellowStore, $BlueStore]] }; StoreOp: TEditInput.CommandProc = { RETURN [ForkViewerOp2[DoStoreFile,viewer]] }; 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]] }; 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] }; 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.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: 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] }; 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]]}; 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]}; 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: PUBLIC Menus.MenuProc = {Do[parent,$Time]}; 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.... ÈTEditDocuments3Impl.mesa Paxton on June 6, 1983 1:58 pm McGregor on August 26, 1982 2:52 pm Maxwell, January 6, 1983 11:11 am Plass, April 15, 1983 1:43 pm Russ Atkinson, July 25, 1983 6:47 pm -- fork so can release input monitor without waiting for call to complete -- HACK: wait 1/4 sec to let other process lock the tdd before we return This is called after Rollback to see if any viewers need to be Reset. Reset Save Clear = Empty, New, or CloseAndNew Don't fork these operations since they change the selection; want to capture typein that follows calls on these. This is the button in the upper left corner. Store PreviousFile = LoadPrevious, OpenPrevious, or CloseAndOpenPrevious Anonymous Loads -- into NoName viewers Get = Load, Open, or CloseAndOpen GetImpl = LoadImpl, OpenImpl, or CloseAndOpenImpl This is the Open button in the upper left corner of the screen. Places menu commands Levels menu commands Lines menu commands Time Split Ê $˜šÏc™Jš™Jš#™#J™!J™J™$J™—šÏk ˜ Jšœžœ˜Jšœžœ˜*Jšœ žœ ˜0Jšœžœ˜$Jšœžœ˜+Jšœžœ˜+Jšœžœ žœ˜J˜J˜Jšœ žœD˜TJ˜ Jšœžœ˜"Jšœžœ˜%Jšœ žœ1˜?Jšœ žœ˜"Jšœžœ˜*Jšœ žœ˜)Jšœ žœ-˜