DIRECTORY Atom, Commander, CommanderOps, Convert, EBTypes, EditedStream, EmbeddedButtons, Feedback, FeedbackOps, FeedbackTypes, FileNames, InputFocus, IO, List, Menus, MessageWindow, NodeProps, ProcessProps, PropRegistry, Rope, RuntimeError, SimpleFeedback, TEditDocument, TEditInput, TEditInputOps, TEditLocks, TEditOps, TEditSelection, TextEdit, TextNode, TiogaActive, TiogaOps, TypeScript, ViewerClasses, ViewerIO, ViewerTools; ButtonApplicationsImpl: CEDAR PROGRAM IMPORTS Atom, CommanderOps, Convert, EditedStream, EmbeddedButtons, Feedback, FeedbackOps, FileNames, InputFocus, IO, List, Menus, MessageWindow, NodeProps, ProcessProps, PropRegistry, Rope, RuntimeError, SimpleFeedback, TEditInput, TEditInputOps, TEditLocks, TEditOps, TEditSelection, TextEdit, TextNode, TiogaActive, TiogaOps, TypeScript, ViewerIO, ViewerTools = BEGIN ActiveButton: TYPE = EBTypes.ActiveButton; ActiveDoc: TYPE = EBTypes.ActiveDoc; ButtonInfo: TYPE = EBTypes.ButtonInfo; RegisteredNotifyProc: TYPE = EmbeddedButtons.RegisteredNotifyProc; ROPE: TYPE = Rope.ROPE; Viewer: TYPE = ViewerClasses.Viewer; TiogaHandler: RegisteredNotifyProc = { viewer: ViewerClasses.Viewer; inputFocus: InputFocus.Focus; events ¬ ProcessEvents[events, buttonInfo.doc]; inputFocus ¬ InputFocus.GetInputFocus[]; IF inputFocus # NIL THEN { viewer ¬ inputFocus.owner; IF viewer # NIL AND (viewer.class.flavor = $Text OR viewer.class.flavor = $Typescript) THEN { TiogaActive.Interpret[viewer, buttonInfo.button, buttonInfo.doc, events]; } ELSE SimpleFeedback.Append[routerName: $EmbeddedButtons, msgType: oneLiner, msgClass: $UserError, msg: "Tioga message handler: input focus not in a Tioga viewer."]; }; }; SyntaxError: PUBLIC SIGNAL[msg: Rope.ROPE] = CODE; ProcessEvents: PROC [events: LIST OF REF ANY, doc: ActiveDoc] RETURNS [newEvents: LIST OF REF ANY] = { z: LIST OF REF ANY; l: LIST OF REF ANY; newEvents ¬ LIST[NIL]; z ¬ newEvents; l ¬ events; DO IF l = NIL THEN EXIT; IF l.first # $EBApplications THEN { z.rest ¬ LIST[l.first]; z ¬ z.rest; l ¬ l.rest; } ELSE { l ¬ l.rest; IF l.first = $GetKeyValue THEN l ¬ GetKeyValue[l, doc] ELSE EmbeddedButtons.Error[Rope.Concat["Embedded buttons applications handler: Unknown function: ", Atom.GetPName[NARROW[l.first]]], Rope.Cat["The Embedded buttons applications handler encountered an unknown function following an $EBApplications atom: ", Atom.GetPName[NARROW[l.first]], ". The button press will be ignored."]]; }; ENDLOOP; newEvents ¬ newEvents.rest; }; GetKeyValue: PROC [l: LIST OF REF ANY, doc: ActiveDoc] RETURNS [newEvents: LIST OF REF ANY ¬ NIL] = { val: REF; key: ATOM; l ¬ l.rest; IF ~ISTYPE[l.first, ATOM] THEN {EmbeddedButtons.Error["Embedded buttons applications handler: Invalid key name in $GetKeyValue", "The Embedded buttons applications handler encountered an unknown object while expecting an ATOM. This occurred while processing a $EBApplications $GetKeyValue."]; RETURN;}; key ¬ NARROW[l.first]; val ¬ EmbeddedButtons.GetValue[key, doc]; newEvents ¬ LIST[val]; newEvents.rest ¬ l.rest; }; MessageWindowHandler: EmbeddedButtons.RegisteredNotifyProc = { PrintRef: PROC [item: REF] = { WITH item SELECT FROM atom: ATOM => eventRope ¬ Rope.Cat[eventRope, " ", Convert.RopeFromAtom[atom]]; rope: Rope.ROPE => eventRope ¬ Rope.Cat[eventRope, " ", Convert.RopeFromRope[rope]]; refInt: REF INT => eventRope ¬ Rope.Cat[eventRope, " ", Convert.RopeFromInt[refInt­]]; refCard: REF CARD => eventRope ¬ Rope.Cat[eventRope, " ", Convert.RopeFromCard[refCard­]]; refChar: REF CHAR => eventRope ¬ Rope.Cat[eventRope, " ", Convert.RopeFromChar[refChar­]]; refBool: REF BOOL => eventRope ¬ Rope.Cat[eventRope, " ", Convert.RopeFromBool[refBool­]]; l: LIST OF REF => { eventRope ¬ Rope.Concat[eventRope, "("]; IF l # NIL THEN { PrintRef[l.first]; FOR list: LIST OF REF ¬ l.rest, list.rest UNTIL list = NIL DO PrintRef[list.first]; ENDLOOP; }; eventRope ¬ Rope.Concat[eventRope, ")"]; }; ENDCASE => eventRope ¬ Rope.Concat[eventRope, " "]; }; eventRope: Rope.ROPE ¬ "Button sends event:"; FOR list: LIST OF REF ANY ¬ events, list.rest UNTIL list = NIL DO IF list.first = NIL THEN eventRope ¬ Rope.Concat[eventRope, " NIL"] ELSE PrintRef[list.first]; ENDLOOP; MessageWindow.Append[message: eventRope, clearFirst: TRUE]; }; TypescriptHandler: EmbeddedButtons.RegisteredNotifyProc = { eventRope: Rope.ROPE ¬ "Button sends event:"; FOR list: LIST OF REF ANY ¬ events, list.rest UNTIL list = NIL DO IF list.first = NIL THEN eventRope ¬ Rope.Concat[eventRope, " NIL"] ELSE WITH list.first SELECT FROM atom: ATOM => eventRope ¬ Rope.Cat[eventRope, " ", Convert.RopeFromAtom[atom]]; rope: Rope.ROPE => eventRope ¬ Rope.Cat[eventRope, " ", Convert.RopeFromRope[rope]]; refInt: REF INT => eventRope ¬ Rope.Cat[eventRope, " ", Convert.RopeFromInt[refInt­]]; refCard: REF CARD => eventRope ¬ Rope.Cat[eventRope, " ", Convert.RopeFromCard[refCard­]]; refChar: REF CHAR => eventRope ¬ Rope.Cat[eventRope, " ", Convert.RopeFromChar[refChar­]]; refBool: REF BOOL => eventRope ¬ Rope.Cat[eventRope, " ", Convert.RopeFromBool[refBool­]]; ENDCASE => eventRope ¬ Rope.Concat[eventRope, " "]; ENDLOOP; SimpleFeedback.Append[routerName: $EmbeddedButtons, msgType: oneLiner, msgClass: $Typescript, msg: eventRope] }; commandsDir: ROPE ~ "/Cedar/Commands/"; tempDir: ROPE ~ "/tmp/"; defaultSearchRules: LIST OF REF ¬ LIST[commandsDir]; defaultPrompt: ROPE ¬ "%l%% %l"; -- from CommandToolImpl CommandToolHandler: EmbeddedButtons.RegisteredNotifyProc = { cmdr: Commander.Handle ¬ NEW[Commander.CommandObject]; out: Rope.ROPE; thisResult: REF; inner: PROC = { cmdr.in ¬ IO.noInputStream; cmdr.out ¬ cmdr.err ¬ FeedbackOps.GetTypescriptStream[$SystemScript]; IF cmdr.out = NIL THEN cmdr.out ¬ cmdr.err ¬ IO.noWhereStream; cmdr.propertyList ¬ LIST[ List.DotCons[key: $ErrorInputStream, val: IO.noInputStream], List.DotCons[key: $Prompt, val: defaultPrompt], List.DotCons[key: $WorkingDirectory, val: tempDir], -- needed? List.DotCons[key: $SearchRules, val: CONS[FileNames.HomeDirectory[], defaultSearchRules]]]; cmdr.procData ¬ NIL; FOR list: LIST OF REF ¬ events, list.rest UNTIL list = NIL DO WITH list.first SELECT FROM commandLine: Rope.ROPE => { thisResult ¬ CommanderOps.DoCommand[commandLine, cmdr]; }; ENDCASE; ENDLOOP; IF thisResult = $Failure THEN result ¬ $Error ELSE result ¬ NIL; }; ProcessProps.AddPropList[ List.PutAssoc[key: $WorkingDirectory, val: tempDir, aList: NIL], inner]; }; ThisCommandToolHandler: EmbeddedButtons.RegisteredNotifyProc = { thisResult: REF; cmdr: Commander.Handle; WITH buttonInfo.doc.theDoc SELECT FROM v: ViewerClasses.Viewer => { IF TypeScript.IsATypeScript[v] THEN { menu: ViewerClasses.Menu ¬ v.menu; menuEntry: ViewerClasses.MenuEntry ¬ Menus.FindEntry[menu, "STOP!"]; clientData: REF; IF menuEntry = NIL THEN RETURN; clientData ¬ Menus.SetClientData[menuEntry, NIL]; [] ¬ Menus.SetClientData[menuEntry, clientData]; WITH clientData SELECT FROM cmd: Commander.Handle => cmdr ¬ cmd; ENDCASE => RETURN; } ELSE RETURN; }; ENDCASE => RETURN; FOR list: LIST OF REF ¬ events, list.rest UNTIL list = NIL DO WITH list.first SELECT FROM commandLine: Rope.ROPE => { commandLine ¬ Rope.Concat[commandLine, "\n"]; SendCommand[commandLine, cmdr]; }; ENDCASE; ENDLOOP; IF thisResult = $Failure THEN result ¬ $Error ELSE result ¬ NIL; }; SendCommand: PROC [commandLine: ROPE, cmdr: Commander.Handle] = { viewer: ViewerClasses.Viewer; viewer ¬ TiogaOps.GetSelection[primary].viewer; WITH ViewerIO.GetViewerFromStream[cmdr.in] SELECT FROM v: ViewerClasses.Viewer => { bufferContents: REF TEXT ¬ ViewerIO.GetBuffer[cmdr.in]; IF bufferContents # NIL AND bufferContents.length > 0 AND bufferContents[bufferContents.length - 1] # '\n THEN { FOR n: NAT DECREASING IN [0..bufferContents.length) DO IF bufferContents[n] = '\n THEN { EditedStream.UnAppendBufferChars[ stream: cmdr.in, nChars: bufferContents.length - n - 1]; EXIT; } REPEAT FINISHED => EditedStream.UnAppendBufferChars[stream: cmdr.in, nChars: LAST[NAT]]; ENDLOOP; }; IF viewer = v THEN { ViewerTools.SetSelection[viewer: viewer, selection: NIL]; }; ViewerIO.TypeChars[editedViewerStream: cmdr.in, chars: commandLine]; }; ENDCASE => MessageWindow.Append["Bug in ButtonApplicationsImpl.SendCommand", TRUE] }; RopeConcat: EBTypes.EBLanguageProc = { rope: ROPE; FOR list: LIST OF REF ¬ arguments, list.rest UNTIL list = NIL DO WITH list.first SELECT FROM r: ROPE => rope ¬ Rope.Concat[rope, r]; ENDCASE; ENDLOOP; RETURN[rope]; }; SelectionText: EBTypes.EBLanguageProc = { RETURN[ViewerTools.GetSelectionContents[]]; }; SelectionPropertyText: EBTypes.EBLanguageProc = { viewer: ViewerClasses.Viewer; start: TiogaOps.Location; key: ATOM; IF arguments = NIL THEN RETURN[NIL]; WITH arguments.first SELECT FROM a: ATOM => key ¬ a; r: ROPE => key ¬ Atom.MakeAtom[r]; ENDCASE => RETURN[NIL]; [viewer, start] ¬ TiogaOps.GetSelection[primary]; IF viewer # NIL AND NOT viewer.destroyed AND NOT viewer.newFile THEN { RETURN[TextEdit.GetCharProp[start.node, start.where, key]]; }; }; FileNameSelection: EBTypes.EBLanguageProc = { curSel: ROPE; viewer: ViewerClasses.Viewer; curSel ¬ ViewerTools.GetSelectionContents[]; curSel ¬ Rope.Substr[base: curSel, start: 0, len: curSel.Index[s2: "\n"]]; -- up to first CR IF (Rope.SkipTo[s: curSel, pos: 0, skip: " \t"] = curSel.Length[]) AND (curSel.Length[] > 1) THEN RETURN[curSel]; viewer ¬ TiogaOps.GetSelection[primary].viewer; IF viewer # NIL AND NOT viewer.destroyed AND NOT viewer.newFile THEN { fileName: ROPE ¬ viewer.file; fileName ¬ Rope.Substr[fileName, 0, Rope.SkipTo[fileName, 0, "!"]]; RETURN[fileName]; }; }; MakeCommanderButtonData: PROC RETURNS [buttonDataRope: Rope.ROPE, commandRope, firstWord: Rope.ROPE] = { commandRope ¬ ViewerTools.GetSelectionContents[]; firstWord ¬ IO.GetTokenRope[IO.RIS[commandRope]].token; buttonDataRope ¬ Rope.Cat["Poppy1\n", "Class: PopUpButton\n", IO.PutFR["Menu: (\n (\"%g\" \"%g\" \"%g\")\n )\n", [rope[Convert.RopeFromRope[commandRope, FALSE]]], [rope[firstWord]], [rope[Convert.RopeFromRope[commandRope, FALSE]]] ], "MessageHandler: CommandTool\n", "Feedback: (\n (MouseMoved )\n )" ]; }; ButtonDataFromSelection: PROC [handlerName: ROPE] RETURNS [buttonDataRope, commandRope: Rope.ROPE] = { commandRope ¬ ViewerTools.GetSelectionContents[]; buttonDataRope ¬ Rope.Cat["Poppy1\n", "Class: PopUpButton\n", IO.PutFLR["Menu: (\n ((%g) \"Do %g Command\" \"Send %g: %g\")\n )\n", LIST[[rope[commandRope]], [rope[handlerName]], [rope[handlerName]], [rope[Convert.RopeFromRope[commandRope, FALSE]]]] ], IO.PutFR1["MessageHandler: %g\n", [rope[handlerName]] ], "Feedback: (\n (MouseMoved )\n )" ]; }; Buttonize: EmbeddedButtons.RegisteredNotifyProc = { viewer: ViewerClasses.Viewer ¬ InputFocus.GetInputFocus[].owner; buttonDataRope: Rope.ROPE; rootOnly: BOOL ¬ FALSE; commandButtonizer: BOOL ¬ IF events = NIL THEN FALSE ELSE events.first = $Command; fromString: BOOL ¬ IF events = NIL THEN FALSE ELSE events.first = $FromString; IF fromString THEN { WITH events.rest.first SELECT FROM s: ROPE => { buttonDataRope ¬ s; Feedback.PutF[router, oneLiner, $Feedback, "Created button from string provided (%g ...)", [rope[Rope.Substr[buttonDataRope, 0, 30]]] ]; }; ENDCASE => { Feedback.Append[router, oneLiner, $Feedback, "FromString buttonizer couldn't find a string."]; RETURN; }; } ELSE IF commandButtonizer THEN { HandlerName: PROC [events: LIST OF REF] RETURNS [handlerName: ROPE] ~ { IF events = NIL OR events.rest = NIL THEN RETURN["Commander"] ELSE WITH events.rest.first SELECT FROM r: ROPE => RETURN[r]; a: ATOM => RETURN[Atom.GetPName[a]]; ENDCASE => RETURN["MessageWindow"]; -- as a sort of warning indicator }; handlerName: ROPE ¬ HandlerName[events]; IF Rope.Equal[handlerName, "Commander", FALSE] THEN { commandRope, firstWord: Rope.ROPE; [buttonDataRope, commandRope, firstWord] ¬ MakeCommanderButtonData[]; Feedback.PutFL[router, oneLiner, $Feedback, "Created Commander button (%g) (%g).", LIST[[rope[commandRope]], [rope[firstWord]]] ]; } ELSE { commandRope: Rope.ROPE; [buttonDataRope, commandRope] ¬ ButtonDataFromSelection[handlerName]; Feedback.PutFL[router, oneLiner, $Feedback, "Created %g button (%g).", LIST[[rope[handlerName]], [rope[commandRope]]] ]; }; } ELSE buttonDataRope ¬ EmbeddedButtons.GetRope[$ButtonDataLiteral, buttonInfo]; IF viewer.class.flavor = $Text OR viewer.class.flavor = $Typescript THEN { postfixRope: Rope.ROPE ¬ EmbeddedButtons.GetRope[$PostfixLiteral, buttonInfo]; IF buttonDataRope # NIL THEN SetProp[viewer, $ButtonData, buttonDataRope, rootOnly]; IF postfixRope # NIL THEN SetProp[viewer, $Postfix, postfixRope, rootOnly]; } ELSE IF viewer.class.flavor = $ActionArea AND buttonDataRope # NIL THEN { GGSetProp[viewer, $ButtonData, buttonDataRope, rootOnly]; }; }; ButtonizeButtonizer: EmbeddedButtons.RegisteredNotifyProc = { viewer: ViewerClasses.Viewer ¬ InputFocus.GetInputFocus[].owner; buttonDataRope: Rope.ROPE; rootOnly: BOOL ¬ FALSE; commanderButtonizer: BOOL ¬ IF events = NIL THEN FALSE ELSE events.first = $Command; result ¬ Buttonize[events, buttonInfo]; IF commanderButtonizer THEN { commandRope, firstWord: Rope.ROPE; [buttonDataRope, commandRope, firstWord] ¬ MakeCommanderButtonData[]; Feedback.PutFL[router, oneLiner, $Feedback, "Created command buttonizer (%g) (%g)", LIST[[rope[commandRope]], [rope[firstWord]]] ]; } ELSE { Feedback.Append[router, oneLiner, $Feedback, "Creating buttonizer from ButtonDataLiteral"]; buttonDataRope ¬ EmbeddedButtons.GetRope[$ButtonDataLiteral, buttonInfo]; }; IF viewer.class.flavor = $Text OR viewer.class.flavor = $Typescript THEN { postfixRope: Rope.ROPE ¬ EmbeddedButtons.GetRope[$PostfixLiteral, buttonInfo]; IF buttonDataRope # NIL THEN SetProp[viewer, $ButtonDataLiteral, buttonDataRope, rootOnly]; IF postfixRope # NIL THEN SetProp[viewer, $PostfixLiteral, postfixRope, rootOnly]; } ELSE IF viewer.class.flavor = $ActionArea AND buttonDataRope # NIL THEN { GGSetProp[viewer, $ButtonDataLiteral, buttonDataRope, rootOnly]; }; }; UnButtonize: EmbeddedButtons.RegisteredNotifyProc = { viewer: ViewerClasses.Viewer ¬ InputFocus.GetInputFocus[].owner; rootOnly: BOOL ¬ IF events = NIL THEN FALSE ELSE events.first = $Root; IF viewer.class.flavor = $Text OR viewer.class.flavor = $Typescript THEN { RemProp[viewer, $ButtonData, rootOnly]; RemProp[viewer, $ButtonFeedback, rootOnly]; RemProp[viewer, $ButtonTarget, rootOnly]; RemProp[viewer, $Postfix, rootOnly]; } ELSE IF viewer.class.flavor = $ActionArea THEN { GGRemProp[viewer, $ButtonData, rootOnly]; GGRemProp[viewer, $ButtonFeedback, rootOnly]; GGRemProp[viewer, $ButtonTarget, rootOnly]; }; }; SetProp: PROC [viewer: Viewer, key: ATOM, valueRope: Rope.ROPE, rootOnly: BOOL] = { Put: PROC [node: TextNode.Ref, start, size: INT] = { value: REF ~ NodeProps.DoSpecs[key, valueRope]; TextEdit.PutCharProp[node: node, index: start, name: key, value: value, nChars: size, event: TEditInput.CurrentEvent[], root: root] }; pSel: TEditDocument.Selection; root: TextNode.Ref; TEditSelection.LockSel[primary, "ButtonizerImpl.SetProp"]; pSel ¬ TEditOps.GetSelData[]; IF NOT TEditInputOps.CheckReadonly[pSel] THEN { TEditSelection.UnlockSel[primary]; RETURN; }; root ¬ TEditSelection.SelectionRoot[pSel]; [] ¬ TEditLocks.Lock[root, "ButtonizerImpl.SetProp"]; ForEachNode[pSel, Put ! RuntimeError.UNCAUGHT => { MessageWindow.Append["Uncaught error in ButtonizerImpl.SetProp", TRUE]; MessageWindow.Blink[]; CONTINUE; }; ]; TEditSelection.UnlockDocAndPSel[root]; }; RemProp: PROC [viewer: Viewer, key: ATOM, rootOnly: BOOL] = { Rem: PROC [node: TextNode.Ref, start, size: INT] = { TextEdit.PutCharProp[node: node, index: start, name: key, value: NIL, nChars: size, event: TEditInput.CurrentEvent[], root: root] }; pSel: TEditDocument.Selection; root: TextNode.Ref; TEditSelection.LockSel[primary, "ButtonizerImpl.RemProp"]; pSel ¬ TEditOps.GetSelData[]; IF NOT TEditInputOps.CheckReadonly[pSel] THEN { TEditSelection.UnlockSel[primary]; RETURN; }; root ¬ TEditSelection.SelectionRoot[pSel]; [] ¬ TEditLocks.Lock[root, "ButtonizerImpl.RemProp"]; ForEachNode[pSel, Rem ! RuntimeError.UNCAUGHT => { MessageWindow.Append["Uncaught error in ButtonizerImpl.RemProp", TRUE]; MessageWindow.Blink[]; CONTINUE; }; ]; TEditSelection.UnlockDocAndPSel[root]; }; GGSetProp: PROC [viewer: Viewer, key: ATOM, valueRope: Rope.ROPE, rootOnly: BOOL] = { propClass: PropRegistry.RegistryClass; setProp: PropRegistry.PropSetProc; propClass ¬ PropRegistry.GetRegistered[$ActionArea]; IF propClass = NIL THEN RETURN; setProp ¬ propClass.setProp; IF setProp # NIL THEN setProp[key: key, doc: viewer, hint: NIL, prop: valueRope, edited: TRUE]; }; GGRemProp: PROC [viewer: Viewer, key: ATOM, rootOnly: BOOL] = { propClass: PropRegistry.RegistryClass; remProp: PropRegistry.PropRemProc; propClass ¬ PropRegistry.GetRegistered[$ActionArea]; IF propClass = NIL THEN RETURN; remProp ¬ propClass.remProp; IF remProp # NIL THEN remProp[key: key, doc: viewer, hint: NIL, edited: TRUE]; }; ForEachNode: PROC [pSel: TEditDocument.Selection, proc: PROC [node: TextNode.Ref, start: INT, size: INT]] = { FOR node: TextNode.Ref ¬ pSel.start.pos.node, TextNode.StepForward[node] DO start: INT ¬ 0; end: INT ¬ TextEdit.Size[node]; IF node = pSel.start.pos.node AND pSel.start.pos.where # TextNode.NodeItself THEN { start ¬ pSel.start.pos.where; }; IF node = pSel.end.pos.node AND pSel.end.pos.where # TextNode.NodeItself THEN { end ¬ MIN[end, pSel.end.pos.where+1]; }; proc[node: node, start: start, size: end-start]; IF node = pSel.end.pos.node THEN EXIT; ENDLOOP; }; router: FeedbackTypes.MsgRouter ¬ Feedback.EnsureRouter[$EmbeddedButtons]; FeedbackOps.SetMultiTypescript[router, $SystemScript, LIST[$SyntaxError, $InternalError, $Typescript, $UserError, $Feedback]]; FeedbackOps.SetMultiMessageWindow[router, TRUE, LIST[$UserError]]; FeedbackOps.SetMultiMessageWindow[router, FALSE, LIST[$Screen, $Feedback]]; EmbeddedButtons.RegisterApplication[$Tioga, TiogaHandler]; EmbeddedButtons.RegisterApplication[$MessageWindow, MessageWindowHandler]; EmbeddedButtons.RegisterApplication[$Typescript, TypescriptHandler]; EmbeddedButtons.RegisterApplication[$CommandTool, CommandToolHandler]; EmbeddedButtons.RegisterApplication[$ThisCommandTool, ThisCommandToolHandler]; EmbeddedButtons.RegisterApplication[$Buttonizer, Buttonize]; EmbeddedButtons.RegisterApplication[$ButtonizerButtonizer, ButtonizeButtonizer]; EmbeddedButtons.RegisterApplication[$UnButtonizer, UnButtonize]; EmbeddedButtons.RegisterPoppyProc[$Concat, RopeConcat]; EmbeddedButtons.RegisterPoppyProc[$SelectionText, SelectionText]; EmbeddedButtons.RegisterPoppyProc[$SelectionPropertyText, SelectionPropertyText]; EmbeddedButtons.RegisterPoppyProc[$CurrentSelection, SelectionText]; EmbeddedButtons.RegisterPoppyProc[$FileNameSelection, FileNameSelection]; END. Ά ButtonApplicationsImpl.mesa Copyright Σ 1989, 1990, 1991, 1992 by Xerox Corporation. All rights reserved. Goodisman, August 11, 1989 5:29:03 pm PDT Spreitzer, May 7, 1990 12:38 pm PDT Kenneth A. Pier, October 31, 1990 2:16 pm PST Bier, July 11, 1991 5:31 pm PDT Doug Wyatt, April 14, 1992 1:22 pm PDT Willie-s, May 12, 1992 2:40 pm PDT Contents: The implementations of some applications that register themselves with EmbeddedButtons. These applications are current included: $Tioga -- Sends a list of Tioga events (i.e., Tioga macros) to the Tioga input handler $Gargoyle $CommandTool $MessageWindow $Buttonizer $ButtonizerButtonizer PROC[events: LIST OF REF ANY, buttonInfo: ButtonInfo]; events will, for the most part, be a list of Tioga actions, such as (1 ApplyLook). However, if the combination $EBApplications $GetKeyValue $ occurs, the named value is retrieved from the active document. This allows a button to base its operation on any of the values in the docuent. TiogaOps.Interpret[viewer, events]; Format: $GetKeyValue Get key Get the value for that key PROC[events: LIST OF REF ANY, buttonInfo: ButtonInfo]; PROC[events: LIST OF REF ANY, buttonInfo: ButtonInfo]; PROC[events: LIST OF REF ANY, buttonInfo: ButtonInfo] RETURNS [result: REF]; events should be a list of ROPEs, each of which is a CommandLine. We must have a WorkingDirectory property on the ProcessProps or CDs fail PROC[events: LIST OF REF ANY, buttonInfo: ButtonInfo] RETURNS [result: REF]; events should be a list of ROPEs, each of which is a CommandLine. buttonInfo is a button in a CommandTool. Send the commands to the CommandTool in which the button is embedded. What a kludge! Find the the Command.Handle from the STOP! menu button. Copied from CommanderViewerImpl.ButtonImplButtonProc (which implements the buttons made by the CreateButton command). If the selected viewer is the commandtool, then set the caret to the end, or the ViewerIO.TypeChars won't work. PROC [arguments: LIST OF REF ANY, buttonInfo: ButtonInfo, clientData: REF] RETURNS [REF ANY _ NIL]; Take all of the arguments that are ROPEs and concatentate them. PROC [arguments: LIST OF REF ANY, buttonInfo: ButtonInfo, clientData: REF] RETURNS [REF ANY _ NIL]; PROC [arguments: LIST OF REF ANY, buttonInfo: ButtonInfo, clientData: REF] RETURNS [REF ANY _ NIL]; PROC [arguments: LIST OF REF ANY, buttonInfo: ButtonInfo, clientData: REF] RETURNS [REF ANY _ NIL]; Replaced by the current selection if it appears to be a file name, otherwise replaced by the name of the selected viewer. Buttonizers PROC[events: LIST OF REF ANY, buttonInfo: ButtonInfo]; rootOnly: BOOL _ IF events = NIL THEN FALSE ELSE events.first = $Root; PROC[events: LIST OF REF ANY, buttonInfo: ButtonInfo] RETURNS [result: REF]; rootOnly: BOOL _ IF events = NIL THEN FALSE ELSE events.first = $Root; PROC[events: LIST OF REF ANY, buttonInfo: ButtonInfo] GGSetProp: PROC [viewer: Viewer, key: ATOM, valueRope: Rope.ROPE, rootOnly: BOOL] = { IF rootOnly THEN GGUserInput.InputNotify[viewer, LIST[$SetRootProp, Rope.Cat[Atom.GetPName[key], " ", valueRope]]] ELSE GGUserInput.InputNotify[viewer, LIST[$SetProp, Rope.Cat[Atom.GetPName[key], " ", valueRope]]]; }; GGRemProp: PROC [viewer: Viewer, key: ATOM, rootOnly: BOOL] = { IF rootOnly THEN GGUserInput.InputNotify[viewer, LIST[$RemoveRootProp, Atom.GetPName[key]]] ELSE GGUserInput.InputNotify[viewer, LIST[$RemoveProp, Atom.GetPName[key]]]; }; Initialization CreateButton look-alike commands ΚO•NewlineDelimiter –(cedarcode) style™šœ™Jšœ ΟeœC™NJšœ)™)J™#J™-Icode™K™&K™"—J˜šΟnœ„™ŒJ™VJ™ J™ J™J™ J™J™—šΟk ˜ KšœŸœ•˜€—K˜šžœŸœŸœ˜&KšŸœkŸœφ˜κKšœŸ˜—˜KšœŸœ˜*Kšœ Ÿœ˜$Kšœ Ÿœ˜&KšœŸœ(˜BKšŸœŸœŸœ˜KšœŸœ˜$K˜—šž œ˜&Kš Ÿœ ŸœŸœŸœŸœ™6Kšœ―™―K˜Kšœ˜K˜K˜/K™K˜(šŸœŸœŸœ˜K˜š Ÿœ ŸœŸœŸœ$Ÿœ˜]KšΟbœ™#KšœI˜IK˜—KšŸœ ˜€K˜—K˜K˜—Kš ž œŸœŸœ ŸœŸœ˜2šž œŸœ ŸœŸœŸœŸœŸœ ŸœŸœŸœŸœ˜fK˜Kš œŸœŸœŸœŸœ˜Kš œŸœŸœŸœŸœ˜K˜Kšœ ŸœŸœ˜K˜K˜K˜ šŸ˜KšŸœŸœŸœŸœ˜šŸœŸœ˜#Kšœ Ÿœ ˜K˜ K˜ K˜—šŸœ˜K˜ KšŸœŸœ˜6šŸœ˜KšœnŸœ•Ÿœ5˜Δ—K˜—KšŸœ˜K˜—K˜K˜K˜—šž œŸœŸœŸœŸœŸœŸœ ŸœŸœŸœŸœŸœ˜e™K™K™—KšœŸœ˜ KšœŸœ˜ K˜K™K˜ Kš ŸœŸœ ŸœŸœΏŸœEŸœ˜―KšœŸœ ˜K˜K™K˜)K˜Kšœ Ÿœ˜K˜K˜K˜—K˜šžœ*˜>Kš Ÿœ ŸœŸœŸœŸœ™6šžœŸœŸœ˜šŸœŸœŸ˜KšœŸœE˜OKšœ ŸœE˜TKšœŸœŸœG˜VKšœ ŸœŸœI˜ZKšœ ŸœŸœI˜ZKšœ ŸœŸœI˜ZšœŸœŸœŸœ˜K˜(šŸœŸœŸœ˜Kšœ˜š ŸœŸœŸœŸœŸœŸœŸ˜=Kšœ˜KšŸœ˜—K˜—K˜(K˜—KšŸœ/˜6—K˜—KšœŸœ˜-šŸœŸœŸœŸœŸœŸœŸœŸ˜AKšŸœŸœŸœ+˜CšŸœ˜Kšœ˜—KšŸœ˜—K•StartOfExpansion-[message: ROPE, clearFirst: BOOL _ FALSE]šœ5Ÿœ˜;K˜K˜—šžœ*˜;Kš Ÿœ ŸœŸœŸœŸœ™6K™KšœŸœ˜-šŸœŸœŸœŸœŸœŸœŸœŸ˜AKšŸœŸœŸœ+˜CšŸ˜šŸœ ŸœŸ˜KšœŸœE˜OKšœ ŸœE˜TKšœŸœŸœG˜VKšœ ŸœŸœI˜ZKšœ ŸœŸœI˜ZKšœ ŸœŸœI˜ZKšŸœ/˜6——KšŸœ˜—K–P[routerName: ATOM, msgType: Feedback.MsgType, msgClass: ATOM, msg: ROPE]˜mK˜K˜—Kšœ Ÿœ˜'Kšœ Ÿœ ˜Kš œŸœŸœŸœŸœ˜4KšœŸœΟc˜8šžœ*˜šœŸœ˜Kšœ*Ÿœ˜Kšœ%Ÿœ2˜[—KšœŸœ˜š ŸœŸœŸœŸœŸœŸœŸ˜=šŸœ ŸœŸ˜šœŸœ˜K˜7K˜—KšŸœ˜—KšŸœ˜—KšŸœŸœŸœ Ÿœ˜@K˜—šœ˜Kšœ;Ÿœ˜@Kšœ˜—KšœH™HK˜K˜—šžœ*˜@Kš Ÿœ ŸœŸœŸœŸœ0™LKšœA™AK™oKšœ Ÿœ˜Kšœ˜šŸœŸœŸ˜&˜K™GšŸœŸœ˜%K˜"K˜DKšœ Ÿœ˜KšŸœ ŸœŸœŸœ˜Kšœ,Ÿœ˜1K˜0šŸœ ŸœŸ˜K˜$KšŸœŸœ˜—K˜—KšŸœŸœ˜ K˜—KšŸœŸœ˜—š ŸœŸœŸœŸœŸœŸœŸ˜=šŸœ ŸœŸ˜šœŸœ˜K˜-Kšœ˜K˜—KšŸœ˜—KšŸœ˜—KšŸœŸœŸœ Ÿœ˜@K˜K˜—šž œŸœŸœ˜AKšœu™uKšœ˜K˜/šŸœ'ŸœŸ˜6˜KšœŸœŸœ˜7š ŸœŸœŸœŸœ1Ÿœ˜pš ŸœŸœŸ œŸœŸ˜6šŸœŸœ˜!šœ!˜!Kšœ8˜8—KšŸœ˜K˜—KšŸ˜KšŸœ>ŸœŸœ˜QKšŸœ˜—K˜—šŸœ Ÿœ˜Kšœo™oKšœ4Ÿœ˜9Kšœ˜—KšœD˜DK˜—KšŸœFŸœ˜R—K˜K˜—šž œ˜&JšŸœ ŸœŸœŸœŸœ&ŸœŸœŸœŸœŸœ™cJ™?KšœŸœ˜ š ŸœŸœŸœŸœŸœŸœŸ˜@šŸœ ŸœŸ˜KšœŸœ ˜'KšŸœ˜—KšŸœ˜—KšŸœ˜ K˜K˜—šž œ˜)JšŸœ ŸœŸœŸœŸœ&ŸœŸœŸœŸœŸœ™cKšŸœ%˜+K˜K˜—šžœ˜1JšŸœ ŸœŸœŸœŸœ&ŸœŸœŸœŸœŸœ™cKšœ˜Kšœ˜KšœŸœ˜ Kš Ÿœ ŸœŸœŸœŸœ˜$šŸœŸœŸ˜ KšœŸœ ˜KšœŸœ˜"KšŸœŸœŸœ˜—K˜1šŸœ ŸœŸœŸœŸœŸœŸœ˜FKšŸœ5˜;Kšœ˜—K˜K˜—šžœ˜-JšŸœ ŸœŸœŸœŸœ&ŸœŸœŸœŸœŸœ™cKšœy™yKšœŸœ˜ Kšœ˜K˜,KšœK‘˜\KšŸœAŸœŸœŸœ ˜qK˜/šŸœ ŸœŸœŸœŸœŸœŸœ˜FKšœ Ÿœ˜K–)[s: ROPE, pos: INT _ 0, skip: ROPE]˜CKšŸœ ˜K˜—K˜—K™K™ šžœŸœŸœŸœ Ÿœ ŸœŸœ˜hK˜1Kšœ ŸœŸœŸœ˜7˜%K˜KšŸœ[Ÿœ@Ÿœ˜­K˜ Kšœ7˜7K˜—K˜K˜—š žœŸœŸœŸœ$Ÿœ˜fK˜1˜%K˜KšŸœFŸœhŸœ˜ΐKšŸœ6˜8Kšœ7˜7K˜—K˜K˜—šž œ*˜3Kš Ÿœ ŸœŸœŸœŸœ™6K˜K˜@KšœŸœ˜Kš œ ŸœŸœ ŸœŸœŸœŸœ™FKšœ ŸœŸœ˜Kš œŸœŸœ ŸœŸœŸœŸœ˜RKš œ ŸœŸœ ŸœŸœŸœŸœ˜NK˜šŸœ Ÿœ˜šŸœŸœŸ˜"šœŸœ˜ K˜Kšœˆ˜ˆK˜—šŸœ˜ K˜^KšŸœ˜K˜——K˜—šŸœŸœŸœ˜ šž œŸœ ŸœŸœŸœŸœŸœ˜GKš Ÿœ ŸœŸœŸœŸœŸœ ˜=šŸœŸœŸœŸ˜'KšœŸœŸœ˜KšœŸœŸœ˜$KšŸœŸœ4˜E—K˜—Kšœ Ÿœ˜(šŸœ&ŸœŸœ˜5KšœŸœ˜"K˜EKšœSŸœ+˜‚K˜—šŸœ˜KšœŸœ˜K˜EKšœGŸœ-˜xK˜—K˜—KšŸœJ˜NK˜šŸœŸœ#Ÿœ˜JKšœŸœ8˜NKšŸœŸœŸœ8˜TKšŸœŸœŸœ2˜KK˜—š ŸœŸœ#ŸœŸœŸœ˜IKšœ9˜9K˜—K˜K˜—šžœ*˜=Kš Ÿœ ŸœŸœŸœŸœ0™LK˜K˜@KšœŸœ˜Kš œ ŸœŸœ ŸœŸœŸœŸœ™FKšœ ŸœŸœ˜Kš œŸœŸœ ŸœŸœŸœŸœ˜TK˜K˜'K˜šŸœŸœ˜KšœŸœ˜"K˜EKšœTŸœ+˜ƒK˜—šŸœ˜Kšœ[˜[K˜IK˜—K˜šŸœŸœ#Ÿœ˜JKšœŸœ8˜NKšŸœŸœŸœ?˜[KšŸœŸœŸœ9˜RK˜—š ŸœŸœ#ŸœŸœŸœ˜IKšœ@˜@K˜—K˜K˜—šž œ*˜5Kš Ÿœ ŸœŸœŸœŸœ™5K™K˜@Kš œ ŸœŸœ ŸœŸœŸœŸœ˜FK˜šŸœŸœ#Ÿœ˜JKšœ'˜'Kšœ+˜+Kšœ)˜)Kšœ$˜$K˜—šŸœŸœ#Ÿœ˜0Kšœ)˜)Kšœ-˜-Kšœ+˜+K˜—K˜K˜—š žœŸœŸœŸœ Ÿœ˜VšžœŸœ#Ÿœ˜4KšœŸœ%˜/K–’[node: TextEdit.RefTextNode, index: INT, name: ATOM, value: REF ANY, nChars: INT _ 1, event: TextEdit.Event _ NIL, root: TextEdit.RefTextNode _ NIL]šœƒ˜ƒK˜—K˜K˜K˜K˜:K˜šŸœŸœ#Ÿœ˜/Kšœ"˜"KšŸœ˜K˜—K˜*K˜5šœ˜šœ Ÿœ˜KšœAŸœ˜GKšœ˜KšŸœ˜ Kšœ˜—K˜—K˜&K˜K˜—šžœŸœŸœ Ÿœ˜@šžœŸœ#Ÿœ˜4K–’[node: TextEdit.RefTextNode, index: INT, name: ATOM, value: REF ANY, nChars: INT _ 1, event: TextEdit.Event _ NIL, root: TextEdit.RefTextNode _ NIL]šœAΠbkœ=˜K˜—K˜K˜K˜Kšœ:˜:K˜šŸœŸœ#Ÿœ˜/Kšœ"˜"KšŸœ˜K˜—K˜*K˜5šœ˜šœ Ÿœ˜KšœAŸœ˜GKšœ˜KšŸœ˜ Kšœ˜—K˜—K˜&K˜K˜K˜—š ž œŸœŸœŸœ Ÿœ™UKšŸœ Ÿœ!Ÿœ=™rKšŸœ!Ÿœ:™cK™K™—š ž œŸœŸœŸœ Ÿœ˜UKšœ&˜&Kšœ"˜"K˜4KšŸœ ŸœŸœŸœ˜K˜Kš Ÿœ ŸœŸœ&ŸœŸœ˜_K˜K˜—šž œŸœŸœ Ÿœ™?KšŸœ Ÿœ!Ÿœ&™[KšŸœ!Ÿœ#™LK™K™—šž œŸœŸœ Ÿœ˜?Kšœ&˜&Kšœ"˜"K˜4KšŸœ ŸœŸœŸœ˜K˜Kš Ÿœ ŸœŸœ&Ÿœ Ÿœ˜NK˜K˜—š ž œŸœ'ŸœŸœŸœ˜mšŸœFŸ˜KKšœŸœ˜KšœŸœ˜šŸœŸœ,Ÿœ˜SK˜Kšœ˜—šŸœŸœ*Ÿœ˜OKšœŸœ˜%Kšœ˜—Kšœ0˜0KšŸœŸœŸœ˜&KšŸœ˜—K˜K˜—K™Kšœ™K™K˜JKšœ6ŸœD˜~Kšœ*ŸœŸœ˜BKšœ*ŸœŸœ˜KKšœ:˜:KšœJ˜JKšœD˜DK˜FKšœN˜NKšœ<˜