DIRECTORY AMTypes USING [TV, TVToType, TVType, Type, UnderClass], Interpreter USING [Evaluate], IO USING [BreakProc, GetCedarTokenRope, RIS, RopeFromROS, ROS, STREAM, TokenProc], MessageWindow USING [Append, Blink, Clear], PrintTV USING [PrintType], Process USING [Detach], Rope USING [Cat, Concat, Fetch, Find, FromChar, Length, Replace, ROPE, Run, Substr], TiogaOps USING [BackSpace, Break, CallWithLocks, ClearLooks, FirstChild, GetCaret, GetRope, GetSelection, GoToPreviousCharacter, InsertRope, IsComment, Location, Nest, Next, NextPlaceholder, PutProp, PutTextKey, Ref, RegisterAbbrevFailedProc, SaveSelA, SetComment, SetLooks, SetNotComment, SetSelection, ViewerDoc], TiogaOpsDefs USING [Ref], ViewerClasses USING [Viewer], WindowManager USING [UnWaitCursor, WaitCursor]; EditorComfortsBImpl: CEDAR PROGRAM IMPORTS AMTypes, Interpreter, IO, MessageWindow, PrintTV, Process, Rope, TiogaOps, WindowManager = BEGIN Location: TYPE = TiogaOps.Location; ROPE: TYPE = Rope.ROPE; STREAM: TYPE = IO.STREAM; TiogaRef: TYPE = TiogaOpsDefs.Ref; TV: TYPE = AMTypes.TV; Viewer: TYPE = ViewerClasses.Viewer; Expand: PROC RETURNS [BOOL] = { caret: Location _ TiogaOps.GetCaret[]; r: ROPE _ TiogaOps.GetRope[caret.node]; i: INT _ caret.where; WHILE i >= 0 DO IF i=0 OR (IO.TokenProc[Rope.Fetch[r, i - 1]] # other) THEN TRUSTED { Process.Detach[FORK Expand0[Rope.Substr[base: r, start: i, len: caret.where - i], caret]]; RETURN [TRUE]; }; i _ i -1; ENDLOOP; RETURN [FALSE]; }; Expand0: PROC [name: ROPE, caret: Location] = { Expand1: PROC [root: REF] = { IF newName # NIL THEN { TiogaOps.BackSpace[Rope.Length[name]]; TiogaOps.InsertRope[newName]; caret _ TiogaOps.GetCaret[]; }; TiogaOps.SaveSelA[]; TiogaOps.PutProp[n: caret.node, name: $StartOfExpansion, value: expansion]; TiogaOps.PutTextKey[node: caret.node, where: caret.where - 1, key: expansion]; IF Rope.Run[s1: expansion, s2: " -- "] = 4 THEN { expansion _ Rope.Substr[expansion, 4]; TiogaOps.ClearLooks[which: caret]; TiogaOps.InsertRope[" = {"]; TiogaOps.Break[]; TiogaOps.Nest[]; TiogaOps.SetComment[]; TiogaOps.SetLooks[looks: "ck", which: caret]; TiogaOps.InsertRope[expansion]; TiogaOps.ClearLooks[which: caret]; TiogaOps.Break[]; TiogaOps.SetNotComment[]; TiogaOps.InsertRope["Body"]; TiogaOps.Break[]; TiogaOps.InsertRope["};"]; [] _ TiogaOps.NextPlaceholder[dir: backwards, gotoend: FALSE]; } ELSE { TiogaOps.InsertRope[expansion]; TiogaOps.GoToPreviousCharacter[Rope.Length[expansion]]; [] _ TiogaOps.NextPlaceholder[gotoend: FALSE]; }; }; viewer: Viewer _ TiogaOps.GetSelection[].viewer; expansion, newName: ROPE; IF viewer = NIL THEN RETURN; IF Rope.Find[name, "."] = -1 THEN { n: TiogaRef _ TiogaOps.FirstChild[TiogaOps.ViewerDoc[viewer]]; WHILE n # NIL DO r: ROPE = TiogaOps.GetRope[n]; IF NOT TiogaOps.IsComment[n] AND (Rope.Find[r, "PROGRAM"] # -1 OR Rope.Find[r, "MONITOR"] # -1) THEN { name _ Rope.Cat[IO.GetCedarTokenRope[IO.RIS[r]].token, ".", name]; EXIT }; n _ TiogaOps.Next[n]; ENDLOOP; }; MessageWindow.Append[message: Rope.Cat["Evaluating ", name, "..."], clearFirst: TRUE]; WindowManager.WaitCursor[]; [expansion, newName] _ ExpandRecord[name, viewer ! UNWIND => WindowManager.UnWaitCursor[]]; WindowManager.UnWaitCursor[]; IF viewer = TiogaOps.GetSelection[].viewer THEN { IF TiogaOps.GetCaret[] # caret THEN { MessageWindow.Append["Caret has moved, insertion NOT performed.", TRUE]; MessageWindow.Blink[]; RETURN; }; } ELSE TiogaOps.SetSelection[viewer: viewer, start: caret, end: caret]; MessageWindow.Clear[]; IF expansion # NIL THEN IF useLocks THEN TiogaOps.CallWithLocks[proc: Expand1] ELSE Expand1[NIL]; }; ExpandRecord: PROC [name: ROPE, viewer: Viewer] RETURNS [expansion: ROPE, newName: ROPE] = { h: STREAM = IO.ROS[]; i: INT; tv: TV; errorRope: ROPE; noResult: BOOL; type: AMTypes.Type; [tv, errorRope, noResult] _ Interpreter.Evaluate[rope: name]; -- Abort? IF noResult THEN { MessageWindow.Append[errorRope, TRUE]; MessageWindow.Blink[]; GOTO Fail}; type _ AMTypes.TVType[tv]; SELECT AMTypes.UnderClass[type] FROM type => { PrintTV.PrintType[type: AMTypes.TVToType[tv], put: h, width: printWidth, verbose: TRUE]; expansion _ h.RopeFromROS[]; i _ Rope.Find[expansion, "["]; IF i = -1 THEN expansion _ NIL ELSE expansion _ Rope.Concat[" -- ", Rope.Substr[base: expansion, start: i]]; RETURN; }; procedure, signal, error, record => { Expand1: PROC [args: ROPE] RETURNS [expansion: ROPE _ NIL] = { left: ROPE = Rope.FromChar['\001]; right: ROPE = Rope.FromChar['\002]; i, length: INT; i _ 1; expansion _ args; length _ Rope.Length[expansion]; DO n: INT _ -1; -- will be character position of : j: INT _ i; -- will be position of the first character beyond this argument, i.e. the , or ] WHILE j < length DO SELECT Rope.Fetch[expansion, j] FROM '', '\\ => j _ j + 2; '], ', => EXIT; ': => n _ j; '[ => -- default value for this argument is a record constructor. find matching right ] and replace interior by its expansion {count: INT _ 1; k: INT _ j + 1; r: ROPE; nChars: INT; WHILE k < length DO SELECT Rope.Fetch[expansion, k] FROM '', '\\ => {k _ k + 2; LOOP}; '[ => count _ count + 1; '] => IF (count _ count - 1) = 0 THEN EXIT; ENDCASE; k _ k + 1; REPEAT FINISHED => GOTO Fail; -- did not find matching ] ENDLOOP; nChars _ k - j + 1; r _ Expand1[Rope.Substr[base: expansion, start: j, len: nChars]]; expansion _ Rope.Replace[base: expansion, start: j, len: nChars, with: r]; length _ Rope.Length[expansion]; j _ k + (Rope.Length[r] - nChars); }; ENDCASE; j _ j + 1; ENDLOOP; IF n = -1 OR j >= length THEN GOTO Fail; expansion _ Rope.Replace[base: expansion, start: j, len: 0, with: right]; expansion _ Rope.Replace[base: expansion, start: n + 2, len: 0, with: left]; length _ length + 2; i _ j + 3; IF i = length THEN EXIT; ENDLOOP; EXITS Fail => expansion _ args; }; PrintTV.PrintType[type: type, put: h, width: printWidth, verbose: TRUE]; expansion _ h.RopeFromROS[]; IF (i _ Rope.Find[expansion, "RETURNS"]) # -1 THEN expansion _ Rope.Substr[base: expansion, len: i - 1]; i _ Rope.Find[expansion, "["]; IF i = -1 THEN {expansion _ "[]"; RETURN}; expansion _ Rope.Substr[expansion, i]; expansion _ Expand1[expansion]; }; ENDCASE => GO TO Fail; EXITS Fail => expansion _ NIL; }; printWidth: INT _ 250; useLocks: BOOL _ TRUE; TiogaOps.RegisterAbbrevFailedProc[Expand]; END. ξEditorComfortsBImpl.mesa Copyright c 1984, 1985, 1986 by Xerox Corporation. All rights reserved. Created by Teitelman Russ Atkinson (RRA) January 22, 1986 9:48:46 pm PST Doug Wyatt, April 11, 1985 11:13:21 am PST Spreitzer, February 28, 1986 3:27:14 pm PST Eric Nickell, May 5, 1986 3:49:29 pm PDT Types Control-E expansion forked because evaluating the expression might require confirmation. associates a sticky address with the first character in the expansion. expansion is used as the key simply because it is a unique ref. could just as easily have done a gensym. should check and if module not loaded, then search file instead of evaluating user went to some other viewer or exec while waiting. if the tv describes a type, e.g. Commander.CommandProc, don't want the type of that object, which would just be TYPE, but rather the object itself, printed as a type. i is the first character in this argument. find end of argument insert right place holder. work from right so positions accurate. + 2 to skip over the : and the space. the minus one is to delete the space before the RETURNS. important in case of typescripts, so that ctrl-next puts you at the end of the typescript. strips off the PROC, ERROR, RECORD, whatever. Initialization Κ (– "Cedar" style˜code™Kšœ Οmœ=™HK™K™3K™*K™+K™(—K™šΟk ˜ Kšœžœžœ&˜7Kšœ žœ ˜Kš žœžœ žœžœžœ ˜RKšœžœ˜+Kšœžœ ˜Kšœžœ ˜Kšœžœ7žœ˜TKšœ žœ­˜»Kšœ žœ˜Kšœžœ ˜Kšœžœ˜/—K˜šΠblœž œ˜#KšžœžœA˜aKšœž˜K˜—™K™Kšœ žœ˜#Kšžœžœžœ˜Kšžœžœžœžœ˜Kšœ žœ˜"Kšžœžœ žœ˜šœžœ˜$K˜——™K™šΟnœžœžœžœ˜K˜&Kšœžœ ˜'Kšœžœ˜šžœž˜š žœžœžœ*žœžœ˜EKšœE™EKšœžœG˜ZKšžœžœ˜K˜—Kšœ ˜ Kšžœ˜—Kšžœžœ˜K˜—K˜š œžœžœ˜/š œžœžœ˜šžœ žœžœ˜Kšœ&˜&Kšœ˜Kšœ˜Kšœ˜—Kšœ˜KšœK˜KšœN˜NKšœ―™―—šžœ(˜*šžœ˜Kšœ&˜&Kšœ"˜"Kšœ˜K˜K˜K˜Kšœ-˜-Kšœ˜Kšœ"˜"K˜K˜K˜K˜Kšœ˜Kšœ7žœ˜>Kšœ˜—šžœ˜Kšœ!˜!Kšœ7˜7Kšœ'žœ˜.K˜——K˜—Kšœ0˜0Kšœžœ˜Kšžœ žœžœžœ˜šžœžœ˜#KšœN™NKšœ>˜>šžœžœž˜Kšœžœ˜š žœžœžœžœžœ˜fKšœžœžœžœ˜BKšž˜K˜—K˜Kšžœ˜—K˜—K•StartOfExpansionZ[r1: ROPE _ NIL, r2: ROPE _ NIL, r3: ROPE _ NIL, r4: ROPE _ NIL, r5: ROPE _ NIL]šœPžœ˜VK˜šœ0˜0Kšœžœ"˜*—K˜šžœ(˜*šžœ˜šžœžœ˜%KšœBžœ˜HK˜Kšžœ˜K˜—K˜—šžœ@˜EKšœ7™7——Kšœ˜šžœ žœž˜Kšžœ žœ'žœ žœ˜I—K˜—K˜–.[name: ROPE, viewer: ViewerClasses.Viewer]š   œžœžœžœ žœ žœ˜\K–v -- [streamProcs: REF IO.StreamProcs, streamData: REF ANY, propList: Atom.PropList _ NIL, backingStream: STREAM _ NIL]šœžœžœžœ˜Kšœžœ˜Kšœžœ˜Kšœ žœ˜Kšœ žœ˜Kšœ˜KšœG˜Gšžœ žœ˜Kšœ žœ˜&Kšœ˜K–[]šžœ˜ —Kšœ˜šžœž˜$šœ ˜ šœRžœ˜XKšœ¦™¦—K˜Kšœ˜šžœ˜ Kšžœ ž˜KšžœI˜M—Kšžœ˜K˜—šœ%˜%š  œžœžœžœ žœžœ˜>Kšœžœ˜"Kšœžœ˜#Kšœ žœ˜K˜K˜K˜ šž˜Kšœ@™@KšœžœΟc"˜0Kšœžœ‘Jœ˜]šžœ ž˜šžœž˜$Kšœ˜Kšœ žœ˜Kšœ ˜ šœ‘w˜}Kšœžœ˜Kšœžœ ˜Kšœžœ˜Kšœžœ˜ šžœ ž˜šžœž˜$Kšœžœ˜K˜Kšœžœžœžœ˜+Kšžœ˜—Kšœ ˜ Kšž˜Kšžœžœ‘˜2Kšžœ˜—K˜K˜AK˜JK˜ Kšœ"˜"K˜—Kšžœ˜—Kšœ ˜ Kšžœ˜—Kšžœžœ žœžœ˜(šœI˜IKšœA™A—šœL˜LKšœ%™%—Kšœ˜Kšœ ˜ Kšžœ žœžœ˜Kšžœ˜—Kšž˜Kšœ˜Kšœ˜—KšœBžœ˜HK˜šžœ,ž˜2Kšœ5˜5Kšœ“™“—K˜Kšžœžœžœ˜,šœ&˜&Kšœžœžœžœ ™-—Kšœ˜K˜—Kšžœžœžœ˜——Kšžœžœ˜K˜Kšœ žœ˜K˜—™K™Kš œžœžœ˜K˜K˜*K˜—Kšžœ˜K˜—…—’&¨