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]]}; Process.Pause[Process.MsecToTicks[250]]; }; CheckFilesAfterRollback: Booting.RollbackProc = { 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 }; 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: 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: 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, 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[] }; RETURN [FALSE] }; 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] }; 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]]}; 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.... ð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 -- 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™(J™—šÏk ˜ Jšœžœ˜,Jšœžœ˜Jšœ žœ ˜0Jšœžœ˜$Jšœžœ˜+Jšœžœ˜+Jšœžœ žœ˜Jšœžœ5˜HJšœžœÊ˜äJšœ žœD˜TJšœžœ˜"Jšœžœ˜%Jšœ žœ1˜?Jšœžœ ˜Jšœ žœ˜"Jšœ žœ-˜Jšœ žœžœžœ˜?Jšœžœžœžœ˜?Jšžœžœ˜J˜—J˜—™J˜Jšœ žœ,˜?J˜Jšœ žœ+˜=J˜Jšœ žœ*˜;J˜Jšœžœ/˜EJ˜J™—™J˜Jšœ žœ+˜=J˜Jšœ žœ*˜;J˜Jšœ žœ)˜9J˜Jšœžœ.˜CJ˜—™J™Jšœžœ%˜1J˜—™J˜šœžœ˜*Jšœ@˜@—J™—J˜Jšœ2˜2J˜JšœZ˜ZJšœT˜TJšœ˜Jšœ˜Jšœ%˜%Jšœ]˜]Jšœ'˜'Jšœ'˜'Jšœ7˜7Jšœ1˜1Jšœ)˜)Jšœ˜Jšœ˜Jšœ'˜'Jšœ˜Jšœ˜Jšœ/˜/Jšœ!˜!Jšœ˜J˜Jšžœ˜J˜—…—0þAö