<> <> <> <> <> <> DIRECTORY AlgebraClasses, Atom, Basics, BigRats, Bools, Buttons, Commander, Complexes, Containers, Convert, Expressions, Evaluator, FS, FSExtras, Icons, Imager, ImagerBackdoor, ImagerTransformation, InputFocus, Ints, IO, Labels, MathBox, MathConstructors, MathDB, MathDisplayExpr, MathExpr, Matrices, Menus, MessageWindow, Parser, Polynomials, PopUpSelection, Real, Reals, RemoteAlgebra, Rope, Rules, Sequences, Sets, TEditDocument, TEditInputOps, TextEdit, TextNode, TiogaAccess, TiogaOps, TiogaOpsDefs, TIPUser, Variables, VariableSequences, Vectors, VFonts, ViewerClasses, ViewerOps, ViewerTools, ViewExpr, ViewExprOps, XRope; ViewExprImpl: CEDAR PROGRAM IMPORTS AlgebraClasses, BigRats, Bools, Buttons, Commander, Complexes, Containers, Convert, Expressions, Evaluator, FS, FSExtras, Icons, ImagerBackdoor, InputFocus, Ints, IO, Labels, MathBox, MathConstructors, MathDB, MathDisplayExpr, MathExpr, Matrices, Menus, MessageWindow, Parser, Polynomials, PopUpSelection, Real, Reals, RemoteAlgebra, Rope, Rules, Sequences, Sets, TEditInputOps, TextEdit, TiogaAccess, TiogaOps, TIPUser, Variables, VariableSequences, Vectors, VFonts, ViewerOps, ViewerTools, ViewExprOps, XRope EXPORTS ViewExpr, TiogaOpsDefs = BEGIN OPEN AC: AlgebraClasses, BR: BigRats, VARS: Variables, INTS: Ints, SEQ: Sequences, MAT: Matrices, POL: Polynomials, VEC: Vectors, ViewExpr; <> ROPE: TYPE ~ Rope.ROPE; BOX: TYPE ~ MathBox.BOX; Viewer: TYPE ~ ViewerClasses.Viewer; Argument: TYPE ~ MathExpr.Argument; CompoundClass: TYPE ~ MathExpr.CompoundClass; EXPR: TYPE ~ MathExpr.EXPR; DisplayExpr: TYPE ~ MathDisplayExpr.DisplayExpr; Ref: TYPE = REF NodeBody; NodeBody: PUBLIC TYPE ~ TextNode.Body; Object: TYPE ~ AC.Object; Method: TYPE ~ AC.Method; <> fontToViewerSizeRatio: REAL = 75.0; -- magnify from TeX font units to Viewer pixels <> entryHeight: CARDINAL = 15; -- how tall to make each line of items entryVSpace: CARDINAL = 8; -- vertical leading space between lines entryHSpace: CARDINAL = 10; -- horizontal space between items in a line <> kbBuffer: Parser.KbBuffer; setSwap: BOOL _ FALSE; <<*** a+-b hack 7/16/87 ***>> ignoreNextRightBracket: BOOL _ FALSE; <> MakeCaminoItem: Commander.CommandProc = BEGIN [] _ CreateCaminoItem["CaminoRealItem"]; END; CreateCaminoItem: PUBLIC PROC [name: ROPE, object: AlgebraClasses.Object _ NIL] RETURNS [CaminoItem] = BEGIN expr: EXPR _ IF object = NIL THEN NIL ELSE NARROW[AC.ApplyNoLkpNoRecastRef[ AC.LookupMethodInStructure[$toExpr, object.class], LIST[object] ], EXPR]; domain: Object _ IF object = NIL THEN NIL ELSE object.class; my: CaminoItem _ NEW[CaminoItemRec]; myMenu: Menus.Menu _ Menus.CreateMenu[lines: 3]; my.object _ object; my.outer _ Containers.Create[ info: [ name: name, -- name displayed in the caption iconic: TRUE, column: left,-- initially in the left column menu: myMenu, -- displaying our menu command scrollable: FALSE -- inhibit user from scrolling contents ] ]; MakeScratchDomain[my, name, domain]; -- build each (sub)viewer in turn MakeExpr[my, expr]; Menus.AppendMenuEntry[myMenu, Menus.CreateEntry["SetName", SetName, my], 0]; Menus.AppendMenuEntry[myMenu, Menus.CreateEntry["Undo", Undo, my.exprViewer.data], 0]; Menus.AppendMenuEntry[myMenu, Menus.CreateEntry["Scale", Scale, my.exprViewer.data], 0]; Menus.AppendMenuEntry[myMenu, Menus.CreateEntry["Home", Home, my.exprViewer.data], 0]; Menus.AppendMenuEntry[myMenu, Menus.CreateEntry["NewItem", NewItem, my], 0]; Menus.AppendMenuEntry[myMenu, Menus.CreateEntry["ToTioga", ConvertToTioga, my], 0]; Menus.AppendMenuEntry[myMenu, Menus.CreateEntry["SetPtSize", SetPtSize, my], 0]; Menus.AppendMenuEntry[myMenu, Menus.CreateEntry["ToExprRope", ConvertToExprRope, my.exprViewer.data], 0]; Menus.AppendMenuEntry[myMenu, Menus.CreateEntry["ToASRope", ConvertToASRope, my.exprViewer.data], 0]; Menus.AppendMenuEntry[myMenu, Menus.CreateEntry["FromExprRope", ConvertFromExprRope, my.exprViewer.data], 0]; Menus.AppendMenuEntry[myMenu, Menus.CreateEntry[name: "Debug", proc: EnterDebugger, clientData: my.exprViewer.data, guarded: TRUE], 0]; Menus.AppendMenuEntry[myMenu, Menus.CreateEntry["SelectPrimary", SelectEntirePrimary, my.exprViewer.data], 1]; Menus.AppendMenuEntry[myMenu, Menus.CreateEntry["ReplaceWithObject", EnterObject, my.exprViewer.data], 1]; Menus.AppendMenuEntry[myMenu, Menus.CreateEntry["ReplaceWithOperator", ReplaceWithOperator, my.exprViewer.data], 1]; Menus.AppendMenuEntry[myMenu, Menus.CreateEntry["WrapWithOperator", WrapWithOperator, my.exprViewer.data], 1]; Menus.AppendMenuEntry[myMenu, Menus.CreateEntry["SelectCopy", SelectEntireCopy, my.exprViewer.data], 1]; Menus.AppendMenuEntry[myMenu, Menus.CreateEntry["FromTioga", ConvertFromTioga, my], 1]; Menus.AppendMenuEntry[myMenu, Menus.CreateEntry["EvalPrimaryInPlace", EvalPrimaryInPlace, my], 2]; Menus.AppendMenuEntry[myMenu, Menus.CreateEntry["OpPrimaryInPlace", OperatePrimaryInPlace, my], 2]; Menus.AppendMenuEntry[myMenu, Menus.CreateEntry["OpWDInPlace", OperateWorkingDomainInPlace, my], 2]; Menus.AppendMenuEntry[myMenu, Menus.CreateEntry["OpPrimary", OperatePrimaryNew, my], 2]; Menus.AppendMenuEntry[myMenu, Menus.CreateEntry["OpWD", OperateWorkingDomainNew, my], 2]; Menus.AppendMenuEntry[myMenu, Menus.CreateEntry["EvalTiogaInPlace", EvalTiogaInPlace, my], 2]; Menus.AppendMenuEntry[myMenu, Menus.CreateEntry["Algebra", DoAlgebra, my], 2]; ViewerOps.SetMenu[my.outer, myMenu]; -- hint our desired height <> ViewerOps.PaintViewer[my.outer, all];-- reflect above change <> RepaintViewer[my.exprViewer]; RETURN[my]; END; MakeScratchDomain: PROC [caminoItem: CaminoItem, name: ROPE, domain: Object] = BEGIN scratchPadButton, objectDomainButton, workingDomainButton: Buttons.Button; initialName: Rope.ROPE; initialDomain: Rope.ROPE; initialName _ IF name = NIL THEN " " ELSE name; initialDomain _ IF domain = NIL THEN " " ELSE NARROW[AC.ApplyNoLkpNoRecastRef[ AC.LookupMethodInStructure[$shortPrintName, domain], LIST[domain] ], ROPE]; caminoItem.height _ caminoItem.height + entryVSpace; -- space down from the top of the viewer caminoItem.name _ initialName; objectDomainButton _ Buttons.Create[ info: [ name: "Result Domain:", wy: caminoItem.height, <> ww:, -- default the width so that it will be computed for us wh: entryHeight, -- specify rather than defaulting so line is uniform parent: caminoItem.outer, border: TRUE], clientData: caminoItem, -- this will be passed to our button proc proc: Null]; caminoItem.objectDomainViewer _ Labels.Create[ info: [ name: initialDomain, -- initial contents wx: objectDomainButton.wx + objectDomainButton.ww + entryHSpace, wy: caminoItem.height, ww: 30*VFonts.CharWidth['0], -- 30 digits worth of width wh: entryHeight, parent: caminoItem.outer, border: TRUE ] ]; workingDomainButton _ Buttons.Create[ info: [ name: "Working Domain:", wy: caminoItem.height, wx: caminoItem.objectDomainViewer.wx + caminoItem.objectDomainViewer.ww + entryHSpace, <> ww:, -- default the width so that it will be computed for us wh: entryHeight, -- specify rather than defaulting so line is uniform parent: caminoItem.outer, border: TRUE], clientData: caminoItem, -- this will be passed to our button proc proc: SetWorkingDomain]; caminoItem.workingDomainViewer _ Labels.Create[ info: [ name: initialDomain, -- initial contents wx: workingDomainButton.wx + workingDomainButton.ww + entryHSpace, wy: caminoItem.height, ww: 30*VFonts.CharWidth['0], -- 30 digits worth of width wh: entryHeight, parent: caminoItem.outer, border: TRUE ] ]; caminoItem.workingDomain _ domain; caminoItem.height _ caminoItem.height + entryHeight + entryVSpace; -- interline spacing scratchPadButton _ Buttons.Create[ info: [ name: "ScratchPad:", wy: caminoItem.height, <> wh: entryHeight, -- specify rather than defaulting so line is uniform parent: caminoItem.outer, border: TRUE ], proc: PromptScratch, clientData: caminoItem]; -- this will be passed to our button proc caminoItem.scratchPadViewer _ ViewerTools.MakeNewTextViewer[ info: [ parent: caminoItem.outer, wx: scratchPadButton.wx + scratchPadButton.ww + entryHSpace, wy: caminoItem.height+2, ww: 80*VFonts.CharWidth['0], -- 80 digits worth of width wh: entryHeight, data: "", -- initial contents scrollable: FALSE, border: TRUE] ]; <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> caminoItem.height _ caminoItem.height + entryHeight + entryVSpace; -- interline spacing END; PromptScratch: Buttons.ButtonProc = BEGIN <> caminoItem: CaminoItem _ NARROW[clientData]; -- get our data ViewerTools.SetSelection[caminoItem.scratchPadViewer]; -- force the selection END; Null: Buttons.ButtonProc = BEGIN END; MakeExpr: PROC [caminoItem: CaminoItem, expr: EXPR _ NIL] = BEGIN xTab: INTEGER = 10; rule: Rules.Rule _ Rules.Create[ info: [ -- create a bar to separate sections 1 and 2 parent: caminoItem.outer, wy: caminoItem.height, ww: caminoItem.outer.cw, wh: 2]]; Containers.ChildXBound[caminoItem.outer, rule]; -- constrain rule to be width of parent caminoItem.height _ caminoItem.height + 2; -- spacing after rule caminoItem.exprViewer _ CreateExprViewer[ parentItem: caminoItem, x: 0, y: caminoItem.height, w: caminoItem.outer.cw, h: caminoItem.outer.wh - caminoItem.height, expr: expr ]; Containers.ChildXBound[caminoItem.outer, caminoItem.exprViewer]; Containers.ChildYBound[caminoItem.outer, caminoItem.exprViewer]; caminoItem.height _ caminoItem.outer.wh; -- extra space at end END; SetName: Buttons.ButtonProc = BEGIN <> caminoItem: CaminoItem _ NARROW[clientData]; -- get our data caminoItem.name _ ViewerTools.GetContents[caminoItem.scratchPadViewer]; -- get name caminoItem.outer.name _ caminoItem.name; <> ViewerOps.PaintViewer[caminoItem.outer, all]; -- reflect change END; NewItem: Menus.MenuProc ~ { caminoItem: CaminoItem _ NARROW[clientData]; newItem: CaminoItem; domain: Object _ caminoItem.workingDomain; newItem _ CreateCaminoItem["CaminoRealItem", NIL]; <> <> }; <> CreateExprViewer: PROC[parentItem: CaminoItem, x, y, w, h: INTEGER, expr: EXPR _ NIL] RETURNS[Viewer] ~ { <> << Viewer will contain math expression expr. If expr = NIL, then>> << Viewer will contain an empty "placeholder".>> << >> v: Viewer _ NIL; -- expression viewer instance s: ExprViewerData; -- expression viewer state expression: EXPR _ expr; -- intial expression to display in viewer displayExpr: DisplayExpr _ NIL; -- display form of expr displayBox: BOX _ NIL; -- box for displayExpr <> IF expression = NIL THEN expression _ MathConstructors.MakePlaceHolder[]; displayExpr _ MathDisplayExpr.DisplayExprFromExpr[expression]; displayBox _ displayExpr.Format[normal]; <> v _ ViewerOps.CreateViewer[ flavor: $expr, info: [ parent: parentItem.outer, wx: x, wy: y, ww: w, wh:h, scrollable: TRUE, hscrollable: TRUE] ]; <> s _ NARROW[v.data]; s.parentItem _ parentItem; s.displayExpr _ displayExpr; s.lastDisplayExpr _ displayExpr; -- for UNDO s.displayBox _ displayBox; <> <> <> RETURN[v]; }; InitializeExprViewer: ViewerClasses.InitProc ~ { <> self.data _ NEW[ExprViewerDataRec _ [ exprViewer: self, offsetX: 0.0, offsetY: 0.0, scale: 1.0, displayExpr: NIL, displayBox: NIL, physicalBox: NIL]]; }; VerticalScroll: ViewerClasses.ScrollProc ~ { <> s: ExprViewerData _ NARROW[self.data]; -- get viewer state info <> topPercentage: INTEGER _ 100 + Real.Round[((-self.ch + (s.physicalBox.Offset[].y - s.physicalBox.Extents[].descent)) / s.physicalBox.Height[]) * 100]; bottomPercentage: INTEGER _ 100 - Real.Round[((s.physicalBox.Extents[].descent - s.physicalBox.Offset[].y) / s.physicalBox.Height[]) * 100]; SELECT op FROM query => { RETURN[top: MIN[100, MAX[0, topPercentage]], bottom: MAX[0, MIN[100, bottomPercentage]]]; }; up => { s.offsetY _ s.offsetY + amount; ViewerOps.PaintViewer[s.exprViewer, client]; }; down => { s.offsetY _ s.offsetY - amount; ViewerOps.PaintViewer[s.exprViewer, client]; }; thumb => RETURN[]; ENDCASE => ERROR; }; HorizontalScroll: ViewerClasses.HScrollProc ~ { <> s: ExprViewerData _ NARROW[self.data]; -- get viewer state info <> leftPercentage: INTEGER _ Real.Round[((s.physicalBox.Extents[].leftExtent - s.physicalBox.Offset[].x) / s.physicalBox.Width[]) * 100]; rightPercentage: INTEGER _ Real.Round[((self.cw - (s.physicalBox.Offset[].x - s.physicalBox.Extents[].leftExtent)) / s.physicalBox.Width[]) * 100]; SELECT op FROM query => { RETURN[left: MIN[100, MAX[0, leftPercentage]], right: MAX[0, MIN[100, rightPercentage]]]; }; left => { s.offsetX _ s.offsetX - amount; ViewerOps.PaintViewer[s.exprViewer, client]; }; right => { s.offsetX _ s.offsetX + amount; ViewerOps.PaintViewer[s.exprViewer, client]; }; thumb => RETURN[]; ENDCASE => ERROR; }; DestroyExprViewer: ViewerClasses.DestroyProc ~ { <> s: ExprViewerData _ NARROW[self.data]; <> ViewExprOps.UnSelectViewer[self]; <<>> <> ViewExprOps.PaintDequeue[self]; s.exprViewer _ NIL; -- break up circular ref for GC }; NotifyExprViewer: ViewerClasses.NotifyProc ~ { <> <> [] _ InputFocus.SetInputFocus[self]; -- grab the input focus so keyboard events get parsed WITH input.first SELECT FROM xy: TIPUser.TIPScreenCoords => { s: ExprViewerData _ NARROW[self.data]; SELECT input.rest.first FROM $PrimarySelect => { ViewExprOps.Select[$primary, s.exprViewer, MathDisplayExpr.DisplayExprFromCoords[s.displayExpr, xy.mouseX, xy.mouseY ! MathDisplayExpr.noSelection => {ViewExprOps.UnSelect[$primary]; CONTINUE}]]; }; $MoveSelect => { <> IF ~ViewExprOps.Active[$primary] THEN { MessageWindow.Append["Make a primary selection first.", TRUE]; MessageWindow.Blink[]; RETURN; }; ViewExprOps.Select[$move, s.exprViewer, MathDisplayExpr.DisplayExprFromCoords[s.displayExpr, xy.mouseX, xy.mouseY ! MathDisplayExpr.noSelection => {ViewExprOps.UnSelect[$move]; CONTINUE}]]; }; $CopySelect => { <> IF ~ViewExprOps.Active[$primary] THEN { MessageWindow.Append["Make a primary selection first.", TRUE]; MessageWindow.Blink[]; RETURN; }; ViewExprOps.Select[$copy, s.exprViewer, MathDisplayExpr.DisplayExprFromCoords[s.displayExpr, xy.mouseX, xy.mouseY ! MathDisplayExpr.noSelection => {ViewExprOps.UnSelect[$copy]; CONTINUE}]]; }; ENDCASE => HandleUserAction[input.rest.first, self]; }; ENDCASE => HandleUserAction[input.first, self]; -- Tip table didn't do anything with this character; input.first is a REF CHAR <> ViewExprOps.FlushPaintQueue[]; }; SelectionColor: PROC[flavor: ATOM] RETURNS[Imager.Color] ~ { <> << If no such association exists, uses "$Invert" color.>> RETURN[ SELECT flavor FROM $primary => ImagerBackdoor.invert, $copy => ImagerBackdoor.MakeStipple[8421H, TRUE], $move => ImagerBackdoor.MakeStipple[8020H, TRUE], $keyboard => ImagerBackdoor.MakeStipple[00F0H, TRUE], ENDCASE => ImagerBackdoor.invert ]; }; PaintExprViewer: ViewerClasses.PaintProc ~ { -- PROC [self: Viewer, context: Imager.Context, whatChanged: REF, clear: BOOL] RETURNS [quit: BOOL _ FALSE]; <> <<>> <> scaleFactor: REAL _ fontToViewerSizeRatio; -- scaling factor s: ExprViewerData _ NARROW[self.data]; highlight: LIST OF MathDisplayExpr.Selection _ NIL; IF (s.displayExpr = NIL) OR (s.displayBox = NIL) THEN RETURN; -- nothing to paint <> scaleFactor _ scaleFactor * s.scale; s.physicalBox _ MathBox.ChangeOffset[MathBox.Scale[s.displayBox, [scaleFactor, scaleFactor]], [s.offsetX + (scaleFactor * s.displayBox.Extents.leftExtent), s.offsetY + (scaleFactor * s.displayBox.Extents.descent)]]; <> FOR l: LIST OF ATOM _ LIST[$primary, $copy, $move, $keyboard], l.rest UNTIL l = NIL DO IF ViewExprOps.Active[l.first] THEN { selectedViewer: Viewer _ NIL; selectedExpr: DisplayExpr _ NIL; [selectedViewer, selectedExpr] _ ViewExprOps.GetSelection[l.first]; IF selectedViewer = s.exprViewer THEN highlight _ CONS[[selectedExpr, SelectionColor[l.first]], highlight]; }; ENDLOOP; <> MathDisplayExpr.Paint[s.displayExpr, context, s.physicalBox, highlight]; }; RepaintViewer: PUBLIC PROC[viewer: Viewer] ~ { ViewExprOps.PaintEnqueue[viewer]; ViewExprOps.FlushPaintQueue[]; }; Home: Menus.MenuProc ~ { <> s: ExprViewerData _ NARROW[clientData]; s.offsetX _ 0.0; s.offsetY _ 0.0; ViewerOps.PaintViewer[s.exprViewer, client]; ViewerOps.PaintViewer[s.exprViewer, client]; -- seems necessary to get it now }; Scale: Menus.MenuProc ~ { <> << If selected with left button, scale _ scale * 1.5,>> << right button, scale _ scale / 1.5,>> << middle button, scale _ 1.0>> s: ExprViewerData _ NARROW[clientData]; SELECT mouseButton FROM red => {s.scale _ s.scale * 1.5}; yellow => {s.scale _ 1.0}; blue => {s.scale _ s.scale / 1.5}; ENDCASE => ERROR; ViewerOps.PaintViewer[s.exprViewer, client]; }; Undo: Menus.MenuProc ~ { <> <<>> s: ExprViewerData _ NARROW[clientData]; UndoViewer[s.exprViewer]; }; UndoViewer: PROC[viewer: Viewer] ~ { <> <> <<>> state: ExprViewerData _ NARROW[viewer.data]; -- get current state <> ViewExprOps.UnSelectViewer[viewer]; <> SetViewerDisplayExpr[viewer, state.lastDisplayExpr]; ViewExprOps.Select[$primary, viewer, state.displayExpr]; <> ViewerOps.PaintViewer[viewer, client]; }; RegisterExprViewerClass: PROC ~ { <> ViewerOps.RegisterViewerClass[ $expr, NEW[ViewerClasses.ViewerClassRec _ [ init: InitializeExprViewer, destroy: DestroyExprViewer, notify: NotifyExprViewer, tipTable: TIPUser.InstantiateNewTIPTable["ViewExpr.tip"], icon: Icons.NewIconFromFile["Meddle.icons", 0], paint: PaintExprViewer, scroll: VerticalScroll, hscroll: HorizontalScroll ]] ]; }; <> CopySecondaryToPrimary: PROC[] ~ { <> << replaces primary selection by secondary selection.>> <> replacement, primaryExpr, copyExpr: DisplayExpr _ NIL; primaryViewer, copyViewer: Viewer _ NIL; IF ~(ViewExprOps.Active[$primary] AND ViewExprOps.Active[$copy]) THEN { MessageWindow.Append["Insufficient Selections for Copy", TRUE]; MessageWindow.Blink[]; RETURN; }; [primaryViewer, primaryExpr] _ ViewExprOps.GetSelection[$primary]; [copyViewer, copyExpr] _ ViewExprOps.GetSelection[$copy]; replacement _ MathDisplayExpr.Copy[copyExpr]; ReplaceInViewer[primaryViewer, primaryExpr, replacement]; <> ViewExprOps.UnSelect[$primary]; ViewExprOps.UnSelect[$move]; }; }; MoveSecondaryToPrimary: PROC[] ~ { <> << replaces primary selection by move selection and >> << deletes secondary selection.>> <> moveReplacement, primaryExpr, moveExpr: DisplayExpr _ NIL; moveViewer, primaryViewer: Viewer _ NIL; IF ~(ViewExprOps.Active[$primary] AND ViewExprOps.Active[$move]) THEN { MessageWindow.Append["Insufficient Selections for Move", TRUE]; MessageWindow.Blink[]; RETURN; }; [primaryViewer, primaryExpr] _ ViewExprOps.GetSelection[$primary]; [moveViewer, moveExpr] _ ViewExprOps.GetSelection[$move]; moveReplacement _ MathDisplayExpr.Copy[moveExpr]; IF moveViewer = primaryViewer THEN { <> state: ExprViewerData _ NARROW[primaryViewer.data]; placeholder: DisplayExpr _ MathDisplayExpr.DisplayExprFromExpr[MathConstructors.MakePlaceHolder[]]; doubleReplacement: DisplayExpr _ MathDisplayExpr.ReplaceN[state.displayExpr, LIST[[old: primaryExpr, new: moveReplacement], [old: moveExpr, new: placeholder]]]; SetViewerDisplayExpr[primaryViewer, doubleReplacement]; -- mutate viewer expression ViewExprOps.PaintEnqueue[primaryViewer]; } ELSE { <> ReplaceInViewer[primaryViewer, primaryExpr, moveReplacement]; <> ViewExprOps.Select[flavor, viewer, state.displayExpr]; <> [] _ InputFocus.SetInputFocus[viewer]; <> ViewerOps.PaintViewer[viewer, client]; }; ReplaceInViewer: PROC[viewer: Viewer, old, new: DisplayExpr] ~ { <> <> << Reformats the display expression for viewer.>> <> state: ExprViewerData _ NARROW[viewer.data]; replacement: DisplayExpr _ MathDisplayExpr.Replace[state.displayExpr, old, new]; SetViewerDisplayExpr[viewer, replacement]; }; SetViewerDisplayExpr: PROC[viewer: Viewer, replacement: DisplayExpr] ~ { <> <> <> << go thru this procedure to keep "UNDO" information valid.>> <<>> state: ExprViewerData _ NARROW[viewer.data]; -- get current state state.lastDisplayExpr _ state.displayExpr; -- old gets current state.displayExpr _ replacement; -- current gets new state.displayBox _ state.displayExpr.Format[normal]; -- format new }; DeleteSelection: PROC[flavor: ATOM, reselect: BOOL _ TRUE] ~ { <> << Replaces selection with an expression "placeholder".>> << This placeholder remians selected iff reselect is TRUE.>> replacement, selectedExpr: DisplayExpr _ NIL; selectedViewer: Viewer _ NIL; IF ~ViewExprOps.Active[flavor] THEN RETURN; -- return w/o action if seln not active [selectedViewer, selectedExpr] _ ViewExprOps.GetSelection[flavor]; replacement _ MathDisplayExpr.DisplayExprFromExpr[MathConstructors.MakePlaceHolder[]]; ReplaceInViewer[selectedViewer, selectedExpr, replacement]; IF reselect THEN { IF flavor#$keyboard THEN ViewExprOps.Select[flavor, selectedViewer, replacement] ELSE { -- the placeholder for deleted KB selection becomes the primary selection ViewExprOps.UnSelect[$keyboard]; ResetKBBuffer[]; ViewExprOps.Select[$primary, selectedViewer, replacement]; }; } ELSE ViewExprOps.UnSelect[flavor]; }; ResetKBBuffer: PROC ~ { kbBuffer _ [type: none, data: "", savedWrapArg: NIL]; -- reset kbBuffer }; ChangeSelectionFlavor: PROC[oldFlavor, newFlavor: ATOM] ~ { <> selectedViewer: Viewer; selectedExpr: DisplayExpr; IF ~ViewExprOps.Active[oldFlavor] THEN RETURN; -- return w/o action if seln not active [selectedViewer, selectedExpr] _ ViewExprOps.GetSelection[oldFlavor]; ViewExprOps.UnSelect[oldFlavor]; ViewExprOps.Select[newFlavor, selectedViewer, selectedExpr]; }; <> GetPopUpMenuMethod: PROC [selection: INT, names: LIST OF ROPE, menuValueList: LIST OF Method] RETURNS [value: Method _ NIL, name: ROPE _ NIL] ~ { <> FOR l: LIST OF Method _ menuValueList, l.rest UNTIL l = NIL DO selection _ selection - 1; IF selection = 0 THEN {value _ l.first; name _ names.first; EXIT}; names _ names.rest; ENDLOOP; RETURN[value, name]; }; GetPopUpMenuAtom: PROC [selection: INT, menuValueList: LIST OF ATOM] RETURNS [value: ATOM _ NIL] ~ { FOR l: LIST OF ATOM _ menuValueList, l.rest UNTIL l = NIL DO selection _ selection - 1; IF selection = 0 THEN {value _ l.first; EXIT}; ENDLOOP; RETURN[value]; }; <> EnterObject: Menus.MenuProc ~ { <> << Returns without action if any errors (e.g. parsing) occur.>> <> replacement: DisplayExpr _ NIL; opNames: LIST OF ROPE _ LIST["variable", "lowGreekVar", "uppGreekVar", "specialCharacter", "bool", "integer", "rational", "real", "complex", "set", "sequence", "vector", "matrix", "block", "parseRope"]; selection: INT _ 0; ok: BOOL _ TRUE; primaryViewer: Viewer _ NIL; primaryExpr: DisplayExpr _ NIL; textSelection: ROPE _ NIL; <> variable: INT = 1; lowGreekVar: INT = 2; uppGreekVar: INT = 3; specialCharacter: INT = 4; bool: INT = 5; integer: INT = 6; rational: INT = 7; real: INT = 8; complex: INT = 9; set: INT = 10; sequence: INT = 11; vector: INT = 12; matrix: INT = 13; block: INT = 14; parseRope: INT = 15; MakeHat: PUBLIC PROC[] RETURNS[EXPR] ~ { <> RETURN[MathExpr.MakeAtomicExpr[$hat, XRope.FromChar['^, XRope.roman]]]; }; s: ExprViewerData _ NARROW[clientData]; [ok, primaryViewer, primaryExpr] _ CheckSelection[$primary, s.exprViewer]; IF ~ok THEN RETURN; <> selection _ PopUpSelection.Request[header: "Choose Object", choice: opNames]; { ENABLE MathConstructors.badFormat, Convert.Error => { MessageWindow.Append["Input format error.", TRUE]; MessageWindow.Blink[]; GOTO abort; }; <> textSelection _ ViewerTools.GetSelectionContents[]; SELECT selection FROM parseRope => PrimarySelectionFromRope[textSelection]; bool => { replacement _ MathDisplayExpr.DisplayExprFromExpr[MathConstructors.MakeBool[textSelection]]; }; integer => { replacement _ MathDisplayExpr.DisplayExprFromExpr[MathConstructors.MakeInt[textSelection]]; }; rational => { replacement _ MathDisplayExpr.DisplayExprFromExpr[ MathConstructors.MakeFraction[ MathConstructors.MakeInt["0"], MathConstructors.MakeInt["1"] ] ]; }; real => { replacement _ MathDisplayExpr.DisplayExprFromExpr[MathConstructors.MakeReal[Convert.RealFromRope[textSelection]]]; }; complex => { replacement _ MathDisplayExpr.DisplayExprFromExpr[ MathConstructors.MakeComplex[ MathConstructors.MakeReal[Convert.RealFromRope["0.0"] ], MathConstructors.MakeReal[Convert.RealFromRope["0.0"] ] ] ]; }; variable => { replacement _ MathDisplayExpr.DisplayExprFromExpr[MathConstructors.MakeVariable[textSelection]]; }; lowGreekVar => { <> greekName: ROPE _ NIL; greekChoices: LIST OF ROPE _ LIST["alpha", "beta", "gamma", "delta", "epsilon", "zeta", "eta", "theta", "iota", "kappa", "lambda", "mu", "nu", "xi", "pi", "rho", "sigma", "tau", "upsilon", "phi", "chi", "psi", "omega"]; <> selection _ PopUpSelection.Request[header: "Choose Variable", choice: greekChoices]; IF selection < 1 THEN RETURN; -- timeout or no selection FOR l: LIST OF ROPE _ greekChoices, l.rest UNTIL l = NIL DO < ATOM)>> selection _ selection - 1; IF selection = 0 THEN {greekName _ l.first; EXIT}; ENDLOOP; replacement _ MathDisplayExpr.DisplayExprFromExpr[MathConstructors.MakeGreekVar[greekName]]; }; uppGreekVar => { <> greekName: ROPE _ NIL; greekChoices: LIST OF ROPE _ LIST["Gamma", "Delta", "Theta", "Lambda", "Xi", "Pi", "Sigma", "Upsilon", "Phi", "Psi", "Omega"]; <> selection _ PopUpSelection.Request[header: "Choose Variable", choice: greekChoices]; IF selection < 1 THEN RETURN; -- timeout or no selection FOR l: LIST OF ROPE _ greekChoices, l.rest UNTIL l = NIL DO < ATOM)>> selection _ selection - 1; IF selection = 0 THEN {greekName _ l.first; EXIT}; ENDLOOP; replacement _ MathDisplayExpr.DisplayExprFromExpr[MathConstructors.MakeGreekVar[greekName]]; }; specialCharacter => { <> specialCharName: ROPE _ NIL; specialCharChoices: LIST OF ROPE _ LIST["infinity", "rightArrow", "bar", "perp", "hat"]; infinity: INT = 1; rightArrow: INT = 2; bar: INT = 3; perp: INT = 4; hat: INT = 5; <> selection _ PopUpSelection.Request[header: "Choose Special Char", choice: specialCharChoices]; SELECT selection FROM infinity => { replacement _ MathDisplayExpr.DisplayExprFromExpr[MathConstructors.MakeInfinity[]]; }; rightArrow => { replacement _ MathDisplayExpr.DisplayExprFromExpr[MathExpr.MakeAtomicExpr[$rightArrow, "\041"] ]; }; bar => { replacement _ MathDisplayExpr.DisplayExprFromExpr[MathExpr.MakeAtomicExpr[$bar, "\000"] ]; }; perp => { replacement _ MathDisplayExpr.DisplayExprFromExpr[MathExpr.MakeAtomicExpr[$perp, "\077"] ]; }; hat => { replacement _ MathDisplayExpr.DisplayExprFromExpr[MakeHat[]]; }; ENDCASE => RETURN; }; set, vector, sequence, block => { <> << whose size and type (row, col) is chosen from a series of pop-up menus.>> << Returns without action if any errors occur.>> oneToTen: LIST OF ROPE _ LIST["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]; dimension: INT _ 0; elements: LIST OF EXPR _ NIL; row: INT _ 0; -- =1 => row vector, =2 => col vector, ELSE => invalid rowVec: BOOL _ FALSE; -- TRUE iff vector is a row vector ok: BOOL _ TRUE; row _ PopUpSelection.Request[header: "Type", choice: LIST["row", "column"]]; IF (row < 1) OR (row > 2) THEN RETURN; -- no selection or timeout IF row = 1 THEN rowVec _ TRUE; dimension _ PopUpSelection.Request[header: "Dimension", choice: oneToTen]; IF (dimension < 1) THEN RETURN; -- no selection or timeout FOR i: INT IN [1..dimension] DO elements _ CONS[MathConstructors.MakeInt["0"], elements]; -- zero entries ENDLOOP; SELECT selection FROM set => replacement _ MathDisplayExpr.DisplayExprFromExpr[MathConstructors.MakeSet[dimension, elements, rowVec]]; block => replacement _ MathDisplayExpr.DisplayExprFromExpr[MathConstructors.MakePoint[dimension, elements, rowVec]]; vector => replacement _ MathDisplayExpr.DisplayExprFromExpr[MathConstructors.MakeVector[dimension, elements, rowVec]]; sequence => replacement _ MathDisplayExpr.DisplayExprFromExpr[MathConstructors.MakeSequence[dimension, elements, rowVec]]; ENDCASE; }; matrix => { <> << whose size is chosen from a series op pop-up menus.>> << Returns without action if any errors occur.>> oneToTen: LIST OF ROPE _ LIST["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]; nRows, nCols: INT _ 0; rows: LIST OF LIST OF EXPR _ NIL; ok: BOOL _ TRUE; nRows _ PopUpSelection.Request[header: "# Rows", choice: oneToTen]; IF (nRows < 1) THEN RETURN; -- no selection or timeout nCols _ PopUpSelection.Request[header: "# Cols", choice: oneToTen]; IF (nCols < 1) THEN RETURN; -- no selection or timeout rows _ NIL; -- cons up list of rows FOR r:INT IN [1..nRows] DO currentRow: LIST OF EXPR _ NIL; -- cons up list of elements FOR c:INT IN [1..nCols] DO currentRow _ CONS[MathConstructors.MakeInt["0"], currentRow]; -- zero entries ENDLOOP; rows _ CONS[currentRow, rows]; ENDLOOP; replacement _ MathDisplayExpr.DisplayExprFromExpr[MathConstructors.MakeMatrix[nRows, nCols, rows]]; }; ENDCASE => RETURN; <> IF selection#parseRope THEN { ViewExprOps.UnSelect[$primary]; -- unselect currently active selection ReplaceInViewer[primaryViewer, primaryExpr, replacement] }; <> ViewerOps.PaintViewer[s.exprViewer, client]; }; EXITS abort => NULL; }; ReplaceWithOperator: Menus.MenuProc ~ { ReplaceOrWrap[clientData: clientData, replace: TRUE]; }; WrapWithOperator: Menus.MenuProc ~ { <> ReplaceOrWrap[clientData: clientData, replace: FALSE]; }; GetOpClassName: PROC [opFamilyName: ATOM] RETURNS [opClassName: ATOM _ NIL] ~ { selection: INT _ 0; opNames: LIST OF ATOM _ MathDB.OpFamilyNames[opFamilyName]; selection _ PopUpSelection.Request[ header: Rope.Cat["Choose ", Convert.RopeFromAtom[opFamilyName], " Op"], choice: MathDB.DescriptionsFromNames[opNames] ]; IF (selection < 1) THEN RETURN; -- no selection or timeout opClassName _ NARROW[GetPopUpMenuAtom[selection, opNames] ]; }; ReplaceOrWrap: PROC [clientData: REF ANY, replace: BOOL] ~ { <> selection: INT _ 0; opFamiliesNames: LIST OF ATOM _ MathDB.OpFamiliesNames[]; opClassName: ATOM; opFamilyName: ATOM; ok: BOOL _ TRUE; primaryViewer: Viewer _ NIL; primaryExpr: DisplayExpr _ NIL; s: ExprViewerData _ NARROW[clientData]; -- check primary selection exists [ok, primaryViewer, primaryExpr] _ CheckSelection[$primary, s.exprViewer]; IF ~ok THEN RETURN; selection _ PopUpSelection.Request[header: "Choose Operator Type", choice: MathDB.RopesFromAtoms[opFamiliesNames] ]; IF (selection < 1) THEN RETURN; -- no selection or timeout opFamilyName _ NARROW[GetPopUpMenuAtom[selection, opFamiliesNames] ]; opClassName _ GetOpClassName[opFamilyName]; IF opClassName = NIL THEN RETURN; -- no selection or timeout IF replace THEN ReplaceWithTemplate[opClassName, primaryViewer, primaryExpr, TRUE] ELSE WrapTemplateIntoViewer[opClassName, primaryViewer, primaryExpr, TRUE]; }; UnaryFunction: PROC [name: ATOM, arg: DisplayExpr _ NIL] RETURNS [DisplayExpr] ~ { <> nameExpr: EXPR _ MathConstructors.MakeVariable[Convert.RopeFromAtom[from: name, quote: FALSE] ]; argExpr: EXPR _ IF arg#NIL THEN MathDisplayExpr.ExprFromDisplayExpr[arg] ELSE MathConstructors.MakePlaceHolder[]; funcExpr: EXPR _ MathExpr.MakeCompoundExpr[$unaryFunction, LIST[[$f, nameExpr], [$arg1, argExpr] ] ]; RETURN[MathDisplayExpr.DisplayExprFromExpr[funcExpr] ]; }; MakeTemplate: PROC [class: ATOM, blink: BOOL _ FALSE] RETURNS[replacement, hotArg: DisplayExpr _ NIL]~ { <> <> <> exprClass: CompoundClass; argExprs: LIST OF MathExpr.TaggedMathExpr _ NIL; hotTag: ATOM; -- tag of "hot" argument ok: BOOL _ TRUE; <> exprClass _ MathDB.LookupCompoundClass[class ! MathDB.notFound => { IF blink THEN { MessageWindow.Append["Template Not found", TRUE]; MessageWindow.Blink[]; }; replacement _ UnaryFunction[class]; hotTag _ $arg1; ok _ FALSE; CONTINUE}; ]; <> IF ok THEN { FOR l: LIST OF Argument _ exprClass.arguments, l.rest UNTIL l = NIL DO FOR aliases: LIST OF ATOM _ l.first.aliases, aliases.rest UNTIL aliases = NIL DO IF aliases.first = $aliasHot THEN {hotTag _ l.first.name; EXIT}; ENDLOOP; argExprs _ CONS[[l.first.name, MathConstructors.MakePlaceHolder[]], argExprs]; ENDLOOP; replacement _ MathDisplayExpr.DisplayExprFromExpr[MathExpr.MakeCompoundExpr[class, argExprs]] }; <> FOR l: LIST OF DisplayExpr _ replacement.GetSubExprs[], l.rest UNTIL l = NIL DO IF l.first.Tag[] = hotTag THEN { hotArg _ l.first; EXIT; -- break out of FOR loop }; ENDLOOP; }; ReplaceWithTemplate: PROC [class: ATOM, viewer: Viewer, expr: DisplayExpr, blink: BOOL _ FALSE] ~ { <> <> <> <> replacement, hotArg: DisplayExpr; [replacement, hotArg] _ MakeTemplate[class, blink]; <> ReplaceInViewer[viewer, expr, replacement]; ViewExprOps.UnSelect[$primary]; <> IF hotArg # NIL THEN ViewExprOps.Select[$primary, viewer, hotArg] ELSE ViewExprOps.Select[$primary, viewer, replacement]; <> RepaintViewer[viewer]; }; WrapTemplate: PROC [class: ATOM, expr: DisplayExpr, blink: BOOL _ FALSE] RETURNS[replacement, selectableSibling, wrapArg: DisplayExpr] ~ { <> <> <> exprClass: CompoundClass; -- class data associated with class argExprs: LIST OF MathExpr.TaggedMathExpr _ NIL; hotTag: ATOM; -- tag of "hot" argument ok: BOOL _ TRUE; replacement _ selectableSibling _ wrapArg _ NIL; <> exprClass _ MathDB.LookupCompoundClass[class ! MathDB.notFound => { IF blink THEN { MessageWindow.Append["Template Not found", TRUE]; MessageWindow.Blink[]; }; replacement _ UnaryFunction[class, expr]; hotTag _ $f; -- so selectableSibling will be $arg1 ok _ FALSE; CONTINUE }; ]; <> IF ok THEN { FOR l: LIST OF Argument _ exprClass.arguments, l.rest UNTIL l = NIL DO hot: BOOL _ FALSE; FOR aliases: LIST OF ATOM _ l.first.aliases, aliases.rest UNTIL aliases = NIL DO IF aliases.first = $aliasHot THEN {hotTag _ l.first.name; hot _ TRUE; EXIT}; ENDLOOP; IF hot AND (expr.Class[] # $placeholder) THEN { argExprs _ CONS[[l.first.name, MathDisplayExpr.ExprFromDisplayExpr[expr]], argExprs]; } ELSE { argExprs _ CONS[[l.first.name, MathConstructors.MakePlaceHolder[]], argExprs]; }; ENDLOOP; replacement _ MathDisplayExpr.DisplayExprFromExpr[MathExpr.MakeCompoundExpr[class, argExprs]]; }; <> FOR l: LIST OF DisplayExpr _ replacement.GetSubExprs[], l.rest UNTIL l = NIL DO IF l.first.Tag[] = hotTag THEN { wrapArg _ l.first; selectableSibling _ l.first.SelectableSibling[! MathDisplayExpr.noSelection => CONTINUE]; EXIT; -- break out of FOR loop }; ENDLOOP; }; WrapTemplateIntoViewer: PROC [class: ATOM, viewer: Viewer, expr: DisplayExpr, blink: BOOL _ FALSE] ~ { <> <> <> << The primary selection is changed to be a sibling of the "hot" argument.>> <<>> replacement, selectableSibling, wrapArg: DisplayExpr; [replacement, selectableSibling, wrapArg] _ WrapTemplate[class, expr, blink]; <> ReplaceInViewer[viewer, expr, replacement]; ViewExprOps.UnSelect[$primary]; <> IF selectableSibling # NIL THEN ViewExprOps.Select[$primary, viewer, selectableSibling] ELSE ViewExprOps.Select[$primary, viewer, wrapArg]; RepaintViewer[viewer]; }; <> PlaceHolder: PROC [] RETURNS [DisplayExpr] ~ { RETURN[MathDisplayExpr.DisplayExprFromExpr[MathConstructors.MakePlaceHolder[] ] ]; }; ParseActionFromChar: PROC[c: CHAR] ~ { <> <> << Updates kbBuffer, message window, and $keyboard selection (viewer & expr).>> <> <<>> <> action: Parser.ParseAction; <> IF ~ViewExprOps.Active[$primary] AND ~ViewExprOps.Active[$keyboard] THEN { msg: ROPE _ "Need either a Primary or a Keyboard selection"; MessageWindow.Append[msg, TRUE]; MessageWindow.Blink[]; RETURN; }; <> [kbBuffer, action] _ Parser.ParseKBChar[c, kbBuffer, ViewExprOps.Active[$primary], ViewExprOps.Active[$keyboard] ]; <> WITH action SELECT FROM r: REF Parser.ReplaceAction => { <> selectedViewer: Viewer _ NIL; selectedExpr, replacement: DisplayExpr _ NIL; ok: BOOL _ TRUE; [selectedViewer, selectedExpr] _ ViewExprOps.GetSelection[r.oldSelection ! ViewExprOps.noSelection => {ok _ FALSE; CONTINUE}]; IF ok THEN { SELECT r.replacementType FROM integer => { replacement _ MathDisplayExpr.DisplayExprFromExpr[MathConstructors.MakeInt[r.fromRope]]; }; real => { replacement _ MathDisplayExpr.DisplayExprFromExpr[MathConstructors.MakeReal[Convert.RealFromRope[r.fromRope]]]; }; variable, templateName => { replacement _ MathDisplayExpr.DisplayExprFromExpr[MathConstructors.MakeVariable[r.fromRope]]; }; ENDCASE; -- do nothing here for template SELECT r.replacementType FROM integer, real, variable, templateName => { ReplaceInViewer[selectedViewer, selectedExpr, replacement]; -- do the replace ViewExprOps.UnSelect[r.oldSelection]; ViewExprOps.Select[r.newSelection, selectedViewer, replacement]; -- will repaint viewer to reflect change (i.e. the replacement) }; template => { ReplaceWithTemplate[Convert.AtomFromRope[r.fromRope], selectedViewer, selectedExpr]; }; ENDCASE => ERROR; }; }; -- end of "replace Parse action choice" w: REF Parser.WrapAction => { <> selectedViewer: Viewer _ NIL; selectedExpr: DisplayExpr _ NIL; ok: BOOL _ TRUE; [selectedViewer, selectedExpr] _ ViewExprOps.GetSelection[w.selection ! ViewExprOps.noSelection => {ok _ FALSE; CONTINUE}]; IF ok THEN WrapTemplateIntoViewer[w.class, selectedViewer, selectedExpr]; ResetKBBuffer[]; }; -- end of "wrap Parse action choice" b: REF Parser.BeginMultiCharTemplateAction => { selectedViewer: Viewer _ NIL; selectedExpr, replacement: DisplayExpr _ NIL; ok: BOOL _ TRUE; [selectedViewer, selectedExpr] _ ViewExprOps.GetSelection[b.oldSelection ! ViewExprOps.noSelection => {ok _ FALSE; CONTINUE}]; IF ~ok THEN RETURN; kbBuffer _ [type: templateName, data: "", savedWrapArg: selectedExpr]; -- initialize kbBuffer; data = "" since delimiter is not part of name replacement _ MathDisplayExpr.DisplayExprFromExpr[MathConstructors.MakeVariable["?"]]; ReplaceInViewer[selectedViewer, selectedExpr, replacement]; -- display "?" ViewExprOps.UnSelect[b.oldSelection]; ViewExprOps.Select[$keyboard, selectedViewer, replacement]; }; f: REF Parser.FinishMultiCharTemplateAction => { <> selectedViewer: Viewer _ NIL; selectedExpr, replacement: DisplayExpr _ NIL; ok: BOOL _ TRUE; [selectedViewer, selectedExpr] _ ViewExprOps.GetSelection[$keyboard ! ViewExprOps.noSelection => {ok _ FALSE; CONTINUE}]; IF ~ok THEN ERROR; ReplaceInViewer[selectedViewer, selectedExpr, kbBuffer.savedWrapArg]; -- replace current KB selection with savedWrapArg, giving us a (hook onto a) placeholder we will replace with the completed template WrapTemplateIntoViewer[f.class, selectedViewer, kbBuffer.savedWrapArg]; -- do the wrap ResetKBBuffer[]; }; < UndoViewer[viewer];>> n: REF Parser.NoAction => NULL; -- do nothing; no action ENDCASE => ERROR; }; HandleUserAction: PROC [action: REF, viewer: Viewer _ NIL] ~ { WITH action SELECT FROM refC: REF CHAR => SELECT refC^ FROM '\010 => IF viewer#NIL THEN UndoViewer[viewer] ELSE RETURN; -- pick this one up here since relates to Viewers ENDCASE => ParseActionFromChar[refC^]; ENDCASE => { flavor: ATOM; selectedExpr: DisplayExpr _ NIL; selectedViewer: Viewer _ NIL; ok: BOOL; SELECT action FROM $PrimaryParentSelect, $CopyParentSelect, $MoveParentSelect, $PrimaryChildSelect, $PrimarySiblingSelect => { SELECT action FROM $PrimaryParentSelect, $PrimaryChildSelect, $PrimarySiblingSelect => flavor _ $primary; $CopyParentSelect => flavor _ $copy; $MoveParentSelect => flavor _ $move; ENDCASE; [ok, selectedViewer, selectedExpr] _ CheckSelection[flavor]; IF ~ok THEN RETURN; SELECT action FROM $PrimaryParentSelect, $CopyParentSelect, $MoveParentSelect => { <> ViewExprOps.Select[flavor, selectedViewer, MathDisplayExpr.SelectableParent[selectedExpr ! MathDisplayExpr.noSelection => {CONTINUE}]]; }; $PrimaryChildSelect => { <> ViewExprOps.Select[$primary, selectedViewer, MathDisplayExpr.SelectableChild[selectedExpr ! MathDisplayExpr.noSelection => {CONTINUE}]]; }; $PrimarySiblingSelect => { <> <> sibling: DisplayExpr; state: ExprViewerData; ok: BOOL _ TRUE; sibling _ MathDisplayExpr.SelectableSibling[selectedExpr ! MathDisplayExpr.noSelection => {ok _ FALSE; CONTINUE}]; IF ok THEN { state _ NARROW[selectedViewer.data]; -- get current state state.displayBox _ state.displayExpr.Format[normal]; -- reformat in case function hack happened ViewExprOps.Select[$primary, selectedViewer, sibling]; }; }; ENDCASE => ERROR; }; $PrimaryDelete => { IF ViewExprOps.Active[$primary] THEN DeleteSelection[$primary] ELSE DeleteSelection[$keyboard]; }; $Undo => UndoViewer[viewer]; $SelectEntire => SelectEntireViewer[viewer, $primary]; $SelectionToPrimary => { <> ChangeSelectionFlavor[$keyboard, $primary]; }; $DoPendingCopy => { IF ViewExprOps.Active[$copy] THEN CopySecondaryToPrimary[]; }; $SetSwap => { setSwap _ TRUE; }; $DoPendingMove => { IF ViewExprOps.Active[$move] THEN IF setSwap THEN SwapSecondaryAndPrimary[] ELSE MoveSecondaryToPrimary[]; setSwap _ FALSE; }; $EvalPrimaryInPlace => { primaryViewer: Viewer; primaryDisplayExpr, evalDisplayExpr: DisplayExpr; [primaryViewer, primaryDisplayExpr, evalDisplayExpr,] _ EvalSelection[$primary]; ReplaceInViewer[primaryViewer, primaryDisplayExpr, evalDisplayExpr]; RepaintViewer[primaryViewer]; }; ENDCASE => RETURN; -- take no action given unrecognized TIP actions }; }; ParseActionFromCharNoViewer: PROC[c: CHAR, outerDisplayExpr, primarySelection, keyboardSelection: DisplayExpr] RETURNS[newOuter, newPrimary, newKeyboard: DisplayExpr] ~ { <> <> << Updates kbBuffer, message window, and $keyboard selection (viewer & expr).>> <> <> <> <<>> <> action: Parser.ParseAction; <> newOuter _ outerDisplayExpr; newPrimary _ primarySelection; newKeyboard _ keyboardSelection; <> [kbBuffer, action] _ Parser.ParseKBChar[c, kbBuffer, primarySelection#NIL, keyboardSelection#NIL ]; <> WITH action SELECT FROM r: REF Parser.ReplaceAction => { <> selectedExpr, replacement, hotArg: DisplayExpr _ NIL; selectedExpr _ SELECT r.oldSelection FROM $primary => primarySelection, $keyboard => keyboardSelection, ENDCASE => ERROR; IF selectedExpr=NIL THEN RETURN[outerDisplayExpr, primarySelection, keyboardSelection]; SELECT r.replacementType FROM integer => { replacement _ MathDisplayExpr.DisplayExprFromExpr[MathConstructors.MakeInt[r.fromRope]]; }; real => { replacement _ MathDisplayExpr.DisplayExprFromExpr[MathConstructors.MakeReal[Convert.RealFromRope[r.fromRope]]]; }; variable, templateName => { replacement _ MathDisplayExpr.DisplayExprFromExpr[MathConstructors.MakeVariable[r.fromRope]]; }; ENDCASE; -- do nothing here for template SELECT r.replacementType FROM integer, real, variable, templateName => { newOuter _ MathDisplayExpr.Replace[outerDisplayExpr, selectedExpr, replacement]; SELECT r.newSelection FROM $primary => {newPrimary _ replacement; newKeyboard _ NIL}; $keyboard => {newKeyboard _ replacement; newPrimary _ NIL}; ENDCASE => ERROR; }; template => { ok: BOOL _ TRUE; wrapParen: BOOL; selectableSibling, wrapArg, parent: DisplayExpr; parentClass: ATOM; templateClass: ATOM _ Convert.AtomFromRope[r.fromRope]; parent _ MathDisplayExpr.SelectableParent[selectedExpr ! MathDisplayExpr.noSelection => {ok _ FALSE; CONTINUE} ]; IF ok THEN parentClass _ MathDisplayExpr.Class[parent] ELSE parentClass _ $none; [replacement, hotArg] _ MakeTemplate[templateClass]; <<*** Begin parenthesis hack 7/15/87>> wrapParen _ FALSE; SELECT parentClass FROM $product => SELECT templateClass FROM $sum, $difference => wrapParen _ TRUE; ENDCASE; $pow => SELECT templateClass FROM $product, $sum, $difference => wrapParen _ TRUE; ENDCASE; ENDCASE; IF wrapParen THEN { [replacement, selectableSibling, wrapArg] _ WrapTemplate[$paren, replacement]; -- wrapArg is now a copy of (previous) replacement hotArg _ MathDisplayExpr.SelectableChild[wrapArg]; -- assumes first Argument is hot; }; <<*** End parenthesis hack 7/15/87>> <<>> <<*** Begin a+-b hack 7/16/87>> IF parentClass = $sum AND templateClass = $negation AND MathDisplayExpr.Tag[selectedExpr]=$augend THEN { [replacement, selectableSibling, wrapArg] _ WrapTemplate[$difference, MathDisplayExpr.SelectableSibling[selectedExpr] ]; newOuter _ MathDisplayExpr.Replace[outerDisplayExpr, parent, replacement]; newPrimary _ selectableSibling; newKeyboard _ NIL; -- since we have a nonNIL newPrimary ResetKBBuffer[]; ignoreNextRightBracket _ TRUE; -- ugly hack global var RETURN; }; <<*** End a+-b hack>> <<>> newOuter _ MathDisplayExpr.Replace[outerDisplayExpr, selectedExpr, replacement]; <> IF hotArg#NIL THEN newPrimary _ hotArg ELSE newPrimary _ replacement; newKeyboard _ NIL; -- since we have a nonNIL newPrimary ResetKBBuffer[]; }; ENDCASE => ERROR; }; -- end of "replace Parse action choice" w: REF Parser.WrapAction => { <> selectedExpr, replacement, selectableSibling, wrapArg: DisplayExpr _ NIL; selectedExpr _ SELECT w.selection FROM $primary => primarySelection, $keyboard => keyboardSelection, ENDCASE => ERROR; IF selectedExpr=NIL THEN RETURN[outerDisplayExpr, primarySelection, keyboardSelection]; [replacement, selectableSibling, wrapArg] _ WrapTemplate[w.class, selectedExpr]; newOuter _ MathDisplayExpr.Replace[outerDisplayExpr, selectedExpr, replacement]; <> IF selectableSibling # NIL THEN newPrimary _ selectableSibling ELSE newPrimary _ wrapArg; newKeyboard _ NIL; -- since we have a nonNIL newPrimary ResetKBBuffer[]; }; -- end of "wrap Parse action choice" b: REF Parser.BeginMultiCharTemplateAction => { selectedExpr, replacement: DisplayExpr _ NIL; selectedExpr _ SELECT b.oldSelection FROM $primary => primarySelection, $keyboard => keyboardSelection, ENDCASE => ERROR; IF selectedExpr=NIL THEN RETURN[outerDisplayExpr, primarySelection, keyboardSelection]; kbBuffer _ [type: templateName, data: "", savedWrapArg: selectedExpr]; -- initialize kbBuffer; data = "" since delimiter is not part of name replacement _ MathDisplayExpr.DisplayExprFromExpr[MathConstructors.MakeVariable["?"]]; newOuter _ MathDisplayExpr.Replace[outerDisplayExpr, selectedExpr, replacement]; newKeyboard _ replacement; -- active KB => Primary selection inactive newPrimary _ NIL; }; f: REF Parser.FinishMultiCharTemplateAction => { <> replacement, selectableSibling, wrapArg: DisplayExpr; selectedExpr: DisplayExpr _ keyboardSelection; IF selectedExpr=NIL THEN RETURN[outerDisplayExpr, primarySelection, keyboardSelection]; [replacement, selectableSibling, wrapArg] _ WrapTemplate[f.class, kbBuffer.savedWrapArg]; -- do the wrap of savedWrapArg newOuter _ MathDisplayExpr.Replace[outerDisplayExpr, selectedExpr, replacement]; -- replace current KB selection with completed template <> IF selectableSibling # NIL THEN newPrimary _ selectableSibling ELSE newPrimary _ wrapArg; newKeyboard _ NIL; -- since there's an active Primary selection ResetKBBuffer[]; }; n: REF Parser.NoAction => NULL; -- do nothing; no action ENDCASE => ERROR; }; HandleUserActionNoViewer: PROC [action: REF, outerDisplayExpr, primarySelection, keyboardSelection: DisplayExpr] RETURNS[newOuter, newPrimary, newKeyboard: DisplayExpr] ~ { <> WITH action SELECT FROM refC: REF CHAR => SELECT refC^ FROM '\010 => NULL; -- ^H (UndoViewer) meaningless ENDCASE => { [newOuter, newPrimary, newKeyboard] _ ParseActionFromCharNoViewer[refC^, outerDisplayExpr, primarySelection, keyboardSelection]; RETURN[newOuter, newPrimary, newKeyboard]; }; ENDCASE => { selection: DisplayExpr _ IF primarySelection#NIL THEN primarySelection ELSE keyboardSelection; -- use KB as Primary if need be SELECT action FROM $PrimaryParentSelect => { <> parent: DisplayExpr _ selection; parent _ MathDisplayExpr.SelectableParent[selection ! MathDisplayExpr.noSelection => {CONTINUE}]; RETURN[outerDisplayExpr, parent, NIL]; -- making a Primary => KB _ NIL }; $PrimaryChildSelect => { <> child: DisplayExpr _ selection; child _ MathDisplayExpr.SelectableChild[selection ! MathDisplayExpr.noSelection => {CONTINUE}]; RETURN[outerDisplayExpr, child, NIL]; }; $PrimarySiblingSelect => { <> <> sibling: DisplayExpr _ selection; sibling _ MathDisplayExpr.SelectableSibling[selection ! MathDisplayExpr.noSelection => {CONTINUE}]; RETURN[outerDisplayExpr, sibling, NIL]; }; <<$PrimaryDelete => { -- should be doable in here>> <<$EvalPrimaryInPlace => { -- -- should be doable in here>> ENDCASE => RETURN; -- take no action given unrecognized TIP actions }; }; DisplayExprFromRope: PROC [rope: ROPE] RETURNS[replacement: DisplayExpr]~ { action: REF; outerDisplayExpr: DisplayExpr _ PlaceHolder[]; primarySelection: DisplayExpr _ outerDisplayExpr; keyboardSelection: DisplayExpr _ NIL; -- No KB selection initially ResetKBBuffer[]; FOR i: INT IN [0..Rope.Length[rope]) DO c: CHAR _ Rope.Fetch[rope, i]; SELECT c FROM ', => action _ $PrimarySiblingSelect; '] => action _ $PrimaryParentSelect; ENDCASE => action _ NEW[CHAR _ c]; IF c#'] OR ~ignoreNextRightBracket THEN [outerDisplayExpr, primarySelection, keyboardSelection] _ HandleUserActionNoViewer[action, outerDisplayExpr, primarySelection, keyboardSelection]; -- *** a+-b hack 7/16/87 IF c='] AND ignoreNextRightBracket THEN ignoreNextRightBracket _ FALSE; ENDLOOP; RETURN[outerDisplayExpr]; }; PrimarySelectionFromRope: PROC [rope: ROPE ] ~ { <> okPrimary: BOOL; selectedViewer: Viewer _ NIL; primarySelection, replacement: DisplayExpr; [okPrimary, selectedViewer, primarySelection] _ CheckSelection[$primary]; IF ~okPrimary THEN RETURN; replacement _ DisplayExprFromRope[rope]; ReplaceInViewer[selectedViewer, primarySelection, replacement]; RepaintViewer[selectedViewer]; }; <> SetWorkingDomain: Buttons.ButtonProc = { caminoItem: CaminoItem _ NARROW[clientData]; -- get our data <> opNames: LIST OF ROPE _ LIST["Expressions", "Variables", "Bools", "Integers", "Rationals", "Reals", "Complexes", "SingleSet", "FamilyOfSets", "Sequences", "Vectors", "Matrices", "Polynomials"]; domain: Object; selection: INT _ 0; oneToTen: LIST OF ROPE _ LIST["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]; <> expressions: INT = 1; variables: INT = 2; bools: INT = 3; integers: INT = 4; rationals: INT = 5; reals: INT = 6; complexes: INT = 7; singleSet: INT = 8; familyOfSets: INT = 9; sequences: INT = 10; vectors: INT = 11; matrices: INT = 12; polynomials: INT = 13; <> selection _ PopUpSelection.Request[header: "Set Domain", choice: opNames]; SELECT selection FROM < 1 => RETURN; -- no selection, cancel, or timeout = expressions => domain _ Expressions.MeddleExprs; = variables => domain _ Variables.Variables; = bools => domain _ Bools.Bools; = integers => domain _ Ints.Ints; = rationals => domain _ BigRats.BigRats; = reals => domain _ Reals.Reals; = complexes => domain _ Complexes.Complexes; = singleSet => { underlyingSet: Object _ Sets.FamilyOfSetsFromRope[ViewerTools.GetContents[caminoItem.scratchPadViewer], caminoItem.workingDomain]; domain _ Sets.MakeSingleSetStructure[underlyingSet]; }; = familyOfSets => { domain _ Sets.MakeFamilyOfSetsStructure[caminoItem.workingDomain]; }; = sequences => { domain _ SEQ.MakeSequenceStructure[caminoItem.workingDomain]; }; = vectors => { dimension: NAT _ 0; dimension _ PopUpSelection.Request[header: "Dimension", choice: oneToTen]; IF (dimension < 1) THEN RETURN; -- no selection or timeout domain _ VEC.MakeVectorStructure[caminoItem.workingDomain, dimension]; }; = matrices => { nRows, nCols: INT _ 0; nRows _ PopUpSelection.Request[header: "# Rows", choice: oneToTen]; IF (nRows < 1) THEN RETURN; -- no selection or timeout nCols _ PopUpSelection.Request[header: "# Cols", choice: oneToTen]; IF (nCols < 1) THEN RETURN; -- no selection or timeout domain _ MAT.MakeMatrixStructure[caminoItem.workingDomain, nRows, nCols]; }; = polynomials => { varSeq: VariableSequences.VariableSequence _ SEQ.FromRope[ViewerTools.GetContents[caminoItem.scratchPadViewer], VariableSequences.VariableSequences]; domain _ POL.MakePolynomialStructure[caminoItem.workingDomain, varSeq]; }; ENDCASE; <> caminoItem.workingDomain _ domain; Labels.Set[caminoItem.workingDomainViewer, domain.name ]; }; <> ObjectFromSelection: PROC[flavor: ATOM, thisViewer: Viewer _ NIL] RETURNS [ok: BOOL _ TRUE, selectionViewer: Viewer, selectionExpr: DisplayExpr, object: Object] ~ { expr: EXPR; [ok, selectionViewer, selectionExpr] _ CheckSelection[flavor, thisViewer]; IF NOT ok THEN RETURN[FALSE, NIL, NIL, NIL]; expr _ MathDisplayExpr.ExprFromDisplayExpr[selectionExpr]; object _ Evaluator.Eval[expr]; RETURN[TRUE, selectionViewer, selectionExpr, object]; }; EvalPrimaryInPlace: Menus.MenuProc ~ { caminoItem: CaminoItem _ NARROW[clientData]; primaryViewer: Viewer; primaryDisplayExpr, evalDisplayExpr: DisplayExpr; evalObjectStructure: ROPE; s: ExprViewerData _ NARROW[caminoItem.exprViewer.data]; [primaryViewer, primaryDisplayExpr, evalDisplayExpr, evalObjectStructure] _ EvalSelection[$primary, s.exprViewer]; ReplaceInViewer[primaryViewer, primaryDisplayExpr, evalDisplayExpr]; Labels.Set[caminoItem.objectDomainViewer, evalObjectStructure]; -- set ObjectDomain viewer of caminoItem to evalObjectStructure RepaintViewer[primaryViewer]; }; EvalSelection: PROC [flavor: ATOM, thisViewer: Viewer _ NIL] RETURNS [selectionViewer: Viewer, selectionExpr, result: DisplayExpr, structureName: ROPE] ~ { ok: BOOL _ TRUE; evalExpr: EXPR; evalObject, evalObjectStructure: AC.Object; [ok, selectionViewer, selectionExpr, evalObject] _ ObjectFromSelection[flavor, thisViewer]; IF NOT ok THEN RETURN[selectionViewer, selectionExpr, NIL, NIL]; evalObjectStructure _ evalObject.class; evalExpr _ NARROW[AC.ApplyLkpNoRecastRef[$toExpr, evalObjectStructure, LIST[evalObject] ] ]; RETURN[ selectionViewer, selectionExpr, MathDisplayExpr.DisplayExprFromExpr[evalExpr], NARROW[AC.ApplyNoLkpNoRecastRef[AC.LookupMethodInStructure[$shortPrintName, evalObjectStructure], LIST[evalObjectStructure] ] ] ]; }; RopeFromFile: PROC [filename: ROPE] RETURNS [ROPE] ~ { stream: IO.STREAM _ FS.StreamOpen[filename, $read]; rope: ROPE _ ""; c: CHAR _ stream.GetChar[]; -- toss first newline WHILE NOT stream.EndOf[] DO c _ stream.GetChar[]; IF ~stream.EndOf[] THEN rope _ rope.Cat[Rope.FromChar[c] ]; ENDLOOP; -- toss last newline RETURN[rope]; }; InsertArgInScript: PROC [flavorRope: ROPE, arg: ROPE] ~ { position: INT; script: ROPE _ RopeFromFile[Rope.Cat[flavorRope, "Script"] ]; out: IO.STREAM _ FS.StreamOpen[fileName: Rope.Cat[flavorRope, "In"], accessOptions: $create, wDir: FSExtras.GetWDir[] ]; -- also could use CommandTool.FileNames interface; in any event, FSExtras.GetWDir seems to just be returning /// as WD, i.e. trivial effect. Probably result of call not coming from a Commander.CommandProc position _ Rope.Find[script, "#1"]; -- all scripts should denote arg position as '#1' script _ Rope.Replace[base: script, start: position, len: Rope.Length["#1"], with: arg]; out.PutRope[script]; out.Close[]; }; DoAlgebra: Menus.MenuProc ~ { <> <> <> ok: BOOL; primaryViewer: Viewer _ NIL; primaryExpr: DisplayExpr _ NIL; flavor: ATOM _ SELECT mouseButton FROM red => $SMP, yellow => $Reduce, blue => $Reduce, ENDCASE => ERROR; flavorRope: ROPE = Convert.RopeFromAtom[flavor, FALSE]; algebraRope: ROPE; errmsg: ROPE; outputFileName: ROPE; [ok, primaryViewer, primaryExpr] _ CheckSelection[$primary]; IF ~ok THEN RETURN; algebraRope _ MathDisplayExpr.ASRopeFromDisplayExpr[primaryExpr, flavor]; InsertArgInScript[flavorRope, algebraRope]; [outputFileName, errmsg] _ RemoteAlgebra.DoRemoteAlgebra[flavorRope]; IF errmsg#NIL THEN { MessageWindow.Append[errmsg, TRUE]; MessageWindow.Blink[]; RETURN; }; PrimarySelectionFromRope[RopeFromFile[outputFileName] ]; <> <> <> <> <> }; EvalTiogaInPlace: Menus.MenuProc ~ { <> caminoItem: CaminoItem _ NARROW[clientData]; <> ok: BOOL _ TRUE; evalExpr: EXPR; evalObject, evalObjectStructure: AC.Object; toExprMethod: AC.Method; linearExpr: ROPE; exprVal: EXPR _ NIL; location: TiogaOps.Location _ TiogaOps.GetSelection[primary].start; selection: TextEdit.RefTextNode _ location.node; exprRope: ROPE _ NARROW[TextEdit.GetCharProp[selection, location.where, $MeddleExpr]]; exprPtSize: ROPE _ NARROW[TextEdit.GetCharProp[selection, location.where, $MeddlePtSize]]; exprVal _ MathExpr.ExprFromRope[ StripHeader[exprRope] ! MathExpr.parseError => {ok _ FALSE; CONTINUE}]; evalObject _ Evaluator.Eval[exprVal]; evalObjectStructure _ evalObject.class; toExprMethod _ AC.LookupMethodInStructure[$toExpr, evalObjectStructure]; evalExpr _ NARROW[AC.ApplyNoLkpNoRecastRef[toExprMethod, LIST[evalObject] ] ]; linearExpr _ MathExpr.RopeFromExpr[evalExpr]; PlaceInTioga[caminoItem, linearExpr]; Labels.Set[caminoItem.objectDomainViewer, NARROW[AC.ApplyNoLkpNoRecastRef[AC.LookupMethodInStructure[$shortPrintName, evalObjectStructure], LIST[evalObjectStructure] ] ] ]; -- set ObjectDomain viewer of caminoItem to evalObjectStructure }; <> OperatePrimaryNew: Menus.MenuProc ~ { caminoItem: CaminoItem _ NARROW[clientData]; OperatePrimarySelection[caminoItem, TRUE]; }; OperatePrimaryInPlace: Menus.MenuProc ~ { caminoItem: CaminoItem _ NARROW[clientData]; OperatePrimarySelection[caminoItem, FALSE]; }; OperatePrimarySelection: PROC [caminoItem: CaminoItem, newItem: BOOL _ TRUE, sourceStructureForMethod: Object _ NIL] ~ { opNames: LIST OF ROPE; operators: LIST OF Method; operator: Method; choiceRope: ROPE; refOps: LIST OF REF _ NIL; selection: INT _ 0; firstArg, secondArg: AC.Object _ NIL; args, reCastArgs: LIST OF Object; result: Object; primaryExpr, copyExpr: DisplayExpr _ NIL; primaryViewer, copyViewer: Viewer _ NIL; ok: BOOL; methodStructure: Object _ sourceStructureForMethod; <> IF methodStructure=NIL THEN { [ok, primaryViewer, primaryExpr, firstArg] _ ObjectFromSelection[$primary]; IF NOT ok THEN RETURN; methodStructure _ firstArg.class; }; <<>> <> [opNames, operators] _ AC.BuildClassOperators[methodStructure.class]; selection _ PopUpSelection.Request[header: "Choose operation", choice: opNames]; IF selection < 1 THEN RETURN; -- no selection or timeout [operator, choiceRope] _ GetPopUpMenuMethod[selection, opNames, operators]; <> IF Rope.Equal[choiceRope, "fromRope"] THEN { textSelection: ROPE _ ViewerTools.GetSelectionContents[]; IF ~newItem THEN [ok, primaryViewer, primaryExpr] _ CheckSelection[$primary]; IF NOT ok THEN RETURN; result _ AC.ApplyFromRopeMethod[operator, textSelection, methodStructure]; } ELSE IF Rope.Equal[choiceRope, "canRecast"] OR Rope.Equal[choiceRope, "recast"] THEN { [ok, primaryViewer, primaryExpr, firstArg] _ ObjectFromSelection[$primary]; IF NOT ok THEN RETURN; args _ LIST[firstArg, methodStructure]; result _ AC.ApplyNoLkpNoRecastObject[operator, args]; } <> ELSE { [ok, primaryViewer, primaryExpr, firstArg] _ ObjectFromSelection[$primary]; IF NOT ok THEN RETURN; SELECT operator.type FROM UnaryOp, UnaryPredicate, StructuredToGroundOp, ElementRankOp, CompareToZeroOp, BinaryMixedOp => args _ LIST[firstArg]; UnaryImbedOp => args _ LIST[firstArg, methodStructure]; -- diagonalMatrix is the only expected UnaryImbedOp; these are right args for it BinaryOp, BinaryPredicate, BinaryCompareOp, TernaryMixedOp => { ViewExprOps.UnSelect[$primary]; -- deselect now to prevent unwanted copy if shift key released (10/1/86 - needed?) [ok, copyViewer, copyExpr, secondArg] _ ObjectFromSelection[$copy]; IF NOT ok THEN RETURN; ViewExprOps.UnSelect[$copy]; args _ LIST[firstArg, secondArg]; }; ENDCASE => ERROR; [ok, reCastArgs] _ AC.RecastArgs[operator, methodStructure, args]; IF ~ok THEN { MessageWindow.Append["Unable to recast args", TRUE]; MessageWindow.Blink[]; RETURN }; SELECT operator.type FROM UnaryOp, UnaryPredicate, StructuredToGroundOp, ElementRankOp, BinaryOp, BinaryPredicate, UnaryImbedOp => result _ AC.ApplyNoLkpNoRecastObject[operator, reCastArgs]; BinaryMixedOp, TernaryMixedOp => { -- i.e. vector or sequence map op groundStructure: Object; groundOperator: Method; IF ISTYPE[firstArg.class.data, SEQ.SequenceData] THEN groundStructure _ NARROW[firstArg.class.data, SEQ.SequenceStructureData].elementStructure ELSE IF ISTYPE[firstArg.data, VEC.VectorData] THEN groundStructure _ NARROW[firstArg.class.data, VEC.VectorStructureData].coordinateStructure ELSE RETURN; [opNames, operators] _ AC.BuildClassOperators[groundStructure]; selection _ PopUpSelection.Request[header: "Choose operation", choice: opNames]; IF selection < 1 THEN RETURN; -- no selection or timeout [groundOperator, choiceRope] _ GetPopUpMenuMethod[selection, opNames, operators]; result _ AC.ApplyMixedMethod[operator, reCastArgs, groundOperator]; }; CompareToZeroOp => { sign: Basics.Comparison _ AC.ApplyCompareToZeroMethod[operator, reCastArgs.first]; SELECT sign FROM less => result _ VARS.FromRope["less"]; equal => result _ VARS.FromRope["equal"]; greater => result _ VARS.FromRope["greater"]; ENDCASE => ERROR; }; BinaryCompareOp => { sign: Basics.Comparison _ AC.ApplyBinaryCompareMethod[operator, reCastArgs.first, reCastArgs.rest.first]; SELECT sign FROM less => result _ VARS.FromRope["less"]; equal => result _ VARS.FromRope["equal"]; greater => result _ VARS.FromRope["greater"]; ENDCASE => ERROR; }; ENDCASE => ERROR; }; <
> IF newItem THEN SetResult[caminoItem: caminoItem, name: choiceRope, result: result, newItem: TRUE] -- will use SetViewerDisplayExpr since we are creating a new item ELSE { -- this is similar to SetResult, should be bundled into a proc resultStructure: Object _ result.class; resultExpr: EXPR _ AC.ApplyLkpNoRecastExpr[$toExpr, resultStructure, LIST[result] ]; ReplaceInViewer[primaryViewer, primaryExpr, MathDisplayExpr.DisplayExprFromExpr[resultExpr] ]; Labels.Set[caminoItem.objectDomainViewer, NARROW[AC.ApplyNoLkpNoRecastRef[AC.LookupMethodInStructure[$shortPrintName, resultStructure], LIST[resultStructure] ] ] ]; RepaintViewer[primaryViewer]; }; }; -- End OperateWorkingDomainNew: Menus.MenuProc ~ { caminoItem: CaminoItem _ NARROW[clientData]; OperatePrimarySelection[caminoItem, TRUE, caminoItem.workingDomain]; }; OperateWorkingDomainInPlace: Menus.MenuProc ~ { caminoItem: CaminoItem _ NARROW[clientData]; OperatePrimarySelection[caminoItem, FALSE, caminoItem.workingDomain]; }; SetResult: PROC [caminoItem: CaminoItem, name: ROPE, result: AC.Object, newItem: BOOL _ TRUE] ~ { IF newItem THEN [] _ CreateCaminoItem[name, result] -- ok not to go through SetViewerDisplayExpr filter since we are creating a new item ELSE { resultStructure: Object _ result.class; resultExpr: EXPR _ AC.ApplyLkpNoRecastExpr[$toExpr, resultStructure, LIST[result] ]; resultDisplayExpr: DisplayExpr _ MathDisplayExpr.DisplayExprFromExpr[resultExpr]; SetViewerDisplayExpr[caminoItem.exprViewer, resultDisplayExpr]; caminoItem.name _ caminoItem.outer.name _ name; Labels.Set[caminoItem.objectDomainViewer, NARROW[AC.ApplyNoLkpNoRecastRef[AC.LookupMethodInStructure[$shortPrintName, resultStructure], LIST[resultStructure] ] ] ]; <> <> <<>> ViewerOps.PaintViewer[caminoItem.outer, all] }; }; <> ConvertToASRope: Menus.MenuProc ~ { <> <> v: ViewerTools.Viewer _ NIL; s: ExprViewerData _ NARROW[clientData]; primaryViewer: Viewer _ NIL; primaryExpr: DisplayExpr _ NIL; flavor: ATOM _ SELECT mouseButton FROM red => $SMP, yellow => $Reduce, blue => $AS, ENDCASE => ERROR; IF ~ViewExprOps.Active[$primary] THEN { MessageWindow.Append["Make a primary selection first.", TRUE]; MessageWindow.Blink[]; RETURN; -- no selection }; [primaryViewer, primaryExpr] _ ViewExprOps.GetSelection[$primary]; <> v _ ViewerTools.MakeNewTextViewer[info: [name: Rope.Cat["Algebra System Rope for ", s.exprViewer.name], iconic: FALSE] ]; ViewerTools.SetContents[v, MathDisplayExpr.ASRopeFromDisplayExpr[primaryExpr, flavor]]; }; ConvertToExprRope: Menus.MenuProc ~ { <> <<>> v: ViewerTools.Viewer _ NIL; s: ExprViewerData _ NARROW[clientData]; primaryViewer: Viewer _ NIL; primaryExpr: DisplayExpr _ NIL; ropeVal: ROPE _ NIL; <> IF ~ViewExprOps.Active[$primary] THEN { MessageWindow.Append["Make a primary selection first.", TRUE]; MessageWindow.Blink[]; RETURN; -- no selection, so complain }; <> [primaryViewer, primaryExpr] _ ViewExprOps.GetSelection[$primary]; <> ropeVal _ MathExpr.RopeFromExpr[MathDisplayExpr.ExprFromDisplayExpr[primaryExpr]]; <> v _ ViewerTools.MakeNewTextViewer[info: [name: Rope.Cat["Expr Rope for ", s.exprViewer.name], iconic: FALSE ] ]; ViewerTools.SetContents[v, ropeVal]; }; ConvertFromExprRope: Menus.MenuProc ~ { <> <<>> <> ropeVal: ROPE _ ViewerTools.GetSelectionContents[]; -- get rope from text selection exprVal, primaryExpr: DisplayExpr _ NIL; ok: BOOL _ TRUE; primaryViewer: Viewer _ NIL; <> IF ~ViewExprOps.Active[$primary] THEN { MessageWindow.Append["Make a primary selection first.", TRUE]; MessageWindow.Blink[]; RETURN; -- no selection, so complain }; <> [primaryViewer, primaryExpr] _ ViewExprOps.GetSelection[$primary]; exprVal _ MathDisplayExpr.DisplayExprFromExpr[MathExpr.ExprFromRope[ropeVal ! MathExpr.parseError => {ok _ FALSE; CONTINUE}]]; IF ok THEN { <> ReplaceInViewer[primaryViewer, primaryExpr, exprVal]; ViewExprOps.UnSelect[$primary]; ViewExprOps.FlushPaintQueue[]; -- update viewer contents } ELSE { <> MessageWindow.Append["Expression Format Error.", TRUE]; MessageWindow.Blink[]; }; }; <> <> <<>> <> <> <> <> <> <<>> <> <> <> <> <> <<};>> <<>> <> <<[primaryViewer, primaryExpr] _ ViewExprOps.GetSelection[$primary];>> <<>> <> <> <<>> <> <> <> <<};>> <<>> WriteHeader: PUBLIC PROC [exprRope: ROPE] RETURNS [ROPE] ~ { <
> header: ROPE = "CaminoRealExpressionRepresentationVersion1.1 "; -- January 6, 1987 11:28:10 am PST RETURN[ Rope.Concat[header, exprRope] ]; -- attach header }; StripHeader: PUBLIC PROC [exprRope: ROPE] RETURNS [ROPE] ~ { headerLength: CARDINAL = 50; IF Rope.Equal[Rope.Substr[exprRope,0,6], "Camino"] THEN RETURN[ Rope.Substr[exprRope, headerLength, Rope.Length[exprRope] ] ] ELSE RETURN[exprRope]; }; ConvertToTioga: Menus.MenuProc ~ { metersPerPoint: REAL _ 254.0/720000.0; mmPerPoint: REAL _ 254.0/720.0; topSpace: REAL _ 8.0*mmPerPoint; bottomSpace: REAL _ 4.0*mmPerPoint; TeXToTioga: REAL ~ 20.0; -- default scaling factor from unit-sized TeX Fonts to Tioga MeddleSelectionToRope: PROC [] RETURNS [ROPE] ~ { primaryExpr: MathDisplayExpr.DisplayExpr _ NIL; <> IF ~ViewExprOps.Active[$primary] THEN { MessageWindow.Append["Make a primary selection first.", TRUE]; MessageWindow.Blink[]; RETURN[NIL]; -- no selection, so complain }; <> [----, primaryExpr] _ ViewExprOps.GetSelection[$primary]; <> RETURN[MathExpr.RopeFromExpr[MathDisplayExpr.ExprFromDisplayExpr[primaryExpr] ] ]; }; WriteArtwork: PUBLIC PROC [writer: TiogaAccess.Writer, pointSize: REAL] RETURNS [ok: BOOL _ TRUE] ~ { tc: TiogaAccess.TiogaChar _ [ charSet: 0, char: 'X, looks: ALL[FALSE], format: NIL, comment: TRUE, endOfNode: FALSE, deltaLevel: 0, propList: NIL ]; <> <> <<[] _ Rope.Map[base: rope, action: action];>> <<};>> PutRopeProp: PROC [key: ATOM, val: ROPE] ~ { tc.propList _ CONS[NEW[Atom.DottedPairNode _ [key: key, val: val]], tc.propList]; }; displayBox: MathBox.BOX _ NIL; displayExpr: MathDisplayExpr.DisplayExpr _ NIL; mathExpr: MathExpr.EXPR _ NIL; postfixValue, leading, topLeading, bottomLeading: ROPE _ NIL; -- for postfix properties linearExpr: ROPE _ MeddleSelectionToRope[]; IF linearExpr=NIL THEN RETURN[FALSE]; <> mathExpr _ MathExpr.ExprFromRope[linearExpr ! MathExpr.parseError => {mathExpr _ MathConstructors.MakePlaceHolder[]; CONTINUE}]; <> displayExpr _ MathDisplayExpr.DisplayExprFromExpr[mathExpr]; <> displayBox _ displayExpr.Format[normal]; <> displayBox _ MathBox.Scale[displayBox, [pointSize, pointSize]]; <<>> <> <> <> leading _ Convert.RopeFromReal[displayBox.Height[]]; topLeading _ Convert.RopeFromReal[displayBox.Extents[].ascent + 12.0]; bottomLeading _ Convert.RopeFromReal[displayBox.Extents[].descent + 12.0]; postfixValue _ Rope.Cat[leading, " pt the leading 2 .copy .gt 3 1 .roll .ifelse leading "]; postfixValue _ Rope.Cat[postfixValue, topLeading, " pt the topLeading 2 .copy .gt 3 1 .roll .ifelse topLeading "]; postfixValue _ Rope.Cat[postfixValue, topLeading, " pt the topIndent 2 .copy .gt 3 1 .roll .ifelse topIndent "]; postfixValue _ Rope.Cat[postfixValue, bottomLeading, " pt the bottomLeading 2 .copy .gt 3 1 .roll .ifelse bottomLeading "]; <> <> PutRopeProp[$Postfix, postfixValue]; -- should this be on the Node ?? PutRopeProp[$Artwork, "MeddleExpr"]; PutRopeProp[$MeddleExpr, WriteHeader[linearExpr] ]; PutRopeProp[$MeddlePtSize, pointSizeRope]; <> TiogaAccess.Put[writer, tc]; -- puts everything at once }; caminoItem: CaminoItem _ NARROW[clientData]; pointSizeRope: ROPE _ ViewerTools.GetContents[caminoItem.scratchPadViewer]; pointSize: REAL _ TeXToTioga; selectionViewer: TiogaOps.Viewer _ TiogaOps.GetSelection[primary].viewer; writer: TiogaAccess.Writer _ TiogaAccess.Create[]; locked: PROC [root: TextNode.Ref, tSel: TEditDocument.Selection] ~ { <> TiogaAccess.WriteSelection[writer]; -- replaces the primary selection }; IF NOT Rope.Equal[pointSizeRope,""] THEN pointSize _ Convert.RealFromRope[pointSizeRope]; IF WriteArtwork[writer: writer, pointSize: pointSize] THEN { TEditInputOps.CallWithLocks[locked]; ViewerOps.PaintViewer[viewer: selectionViewer, hint: client]; }; }; PlaceInTioga: PROC [caminoItem: CaminoItem, linearExpr: ROPE] ~ { metersPerPoint: REAL _ 254.0/720000.0; mmPerPoint: REAL _ 254.0/720.0; topSpace: REAL _ 8.0*mmPerPoint; bottomSpace: REAL _ 4.0*mmPerPoint; TeXToTioga: REAL ~ 20.0; -- default scaling factor from unit-sized TeX Fonts to Tioga WriteArtwork: PUBLIC PROC [writer: TiogaAccess.Writer, pointSize: REAL] RETURNS [ok: BOOL _ TRUE] ~ { tc: TiogaAccess.TiogaChar _ [ charSet: 0, char: 'X, looks: ALL[FALSE], format: NIL, comment: TRUE, endOfNode: FALSE, deltaLevel: 0, propList: NIL ]; <> <> <<[] _ Rope.Map[base: rope, action: action];>> <<};>> PutRopeProp: PROC [key: ATOM, val: ROPE] ~ { tc.propList _ CONS[NEW[Atom.DottedPairNode _ [key: key, val: val]], tc.propList]; }; displayBox: MathBox.BOX _ NIL; displayExpr: MathDisplayExpr.DisplayExpr _ NIL; mathExpr: MathExpr.EXPR _ NIL; postfixValue, leading, topLeading, bottomLeading: ROPE _ NIL; -- for postfix properties IF linearExpr=NIL THEN RETURN[FALSE]; <> mathExpr _ MathExpr.ExprFromRope[linearExpr ! MathExpr.parseError => {mathExpr _ MathConstructors.MakePlaceHolder[]; CONTINUE}]; <> displayExpr _ MathDisplayExpr.DisplayExprFromExpr[mathExpr]; <> displayBox _ displayExpr.Format[normal]; <> displayBox _ MathBox.Scale[displayBox, [pointSize, pointSize]]; <<>> <> <> <> leading _ Convert.RopeFromReal[displayBox.Height[]]; topLeading _ Convert.RopeFromReal[displayBox.Extents[].ascent + 12.0]; bottomLeading _ Convert.RopeFromReal[displayBox.Extents[].descent + 12.0]; postfixValue _ Rope.Cat[leading, " pt the leading 2 .copy .gt 3 1 .roll .ifelse leading "]; postfixValue _ Rope.Cat[postfixValue, topLeading, " pt the topLeading 2 .copy .gt 3 1 .roll .ifelse topLeading "]; postfixValue _ Rope.Cat[postfixValue, topLeading, " pt the topIndent 2 .copy .gt 3 1 .roll .ifelse topIndent "]; postfixValue _ Rope.Cat[postfixValue, bottomLeading, " pt the bottomLeading 2 .copy .gt 3 1 .roll .ifelse bottomLeading "]; <> <> PutRopeProp[$Postfix, postfixValue]; -- should this be on the Node ?? PutRopeProp[$Artwork, "MeddleExpr"]; PutRopeProp[$MeddleExpr, WriteHeader[linearExpr] ]; PutRopeProp[$MeddlePtSize, pointSizeRope]; <> TiogaAccess.Put[writer, tc]; -- puts everything at once }; pointSizeRope: ROPE _ ViewerTools.GetContents[caminoItem.scratchPadViewer]; pointSize: REAL _ TeXToTioga; selectionViewer: TiogaOps.Viewer _ TiogaOps.GetSelection[primary].viewer; writer: TiogaAccess.Writer _ TiogaAccess.Create[]; locked: PROC [root: TextNode.Ref, tSel: TEditDocument.Selection] ~ { <> TiogaAccess.WriteSelection[writer]; -- replaces the primary selection }; IF NOT Rope.Equal[pointSizeRope,""] THEN pointSize _ Convert.RealFromRope[pointSizeRope]; IF WriteArtwork[writer: writer, pointSize: pointSize] THEN { TEditInputOps.CallWithLocks[locked]; ViewerOps.PaintViewer[viewer: selectionViewer, hint: client]; }; }; ConvertFromTioga: Menus.MenuProc ~ { <> <<>> <> <> caminoItem: CaminoItem _ NARROW[clientData]; location: TiogaOps.Location _ TiogaOps.GetSelection[primary].start; selection: TextEdit.RefTextNode _ location.node; exprRope: ROPE _ NARROW[TextEdit.GetCharProp[selection, location.where, $MeddleExpr]]; exprPtSize: ROPE _ NARROW[TextEdit.GetCharProp[selection, location.where, $MeddlePtSize]]; exprVal, primaryExpr: DisplayExpr _ NIL; ok: BOOL _ TRUE; primaryViewer: Viewer _ NIL; <> IF ~ViewExprOps.Active[$primary] THEN { MessageWindow.Append["Make a primary selection first.", TRUE]; MessageWindow.Blink[]; RETURN; -- no selection, so complain }; <> [primaryViewer, primaryExpr] _ ViewExprOps.GetSelection[$primary]; <> exprVal _ MathDisplayExpr.DisplayExprFromExpr[MathExpr.ExprFromRope[ StripHeader[exprRope] ! MathExpr.parseError => {ok _ FALSE; CONTINUE}] ]; IF ok THEN { <> ReplaceInViewer[primaryViewer, primaryExpr, exprVal]; ViewerTools.SetContents[caminoItem.scratchPadViewer, exprPtSize]; ViewExprOps.UnSelect[$primary]; ViewExprOps.FlushPaintQueue[]; -- update viewer contents } ELSE { <> MessageWindow.Append["Expression Format Error.", TRUE]; MessageWindow.Blink[]; }; }; SetPtSize: Menus.MenuProc ~ { <> TeXToTioga: REAL ~ 20.0; -- default scaling factor from unit-sized TeX Fonts to Tioga WriteArtwork: PUBLIC PROC [writer: TiogaAccess.Writer, pointSize: REAL] RETURNS [ok: BOOL _ TRUE] ~ { tc: TiogaAccess.TiogaChar _ [ charSet: 0, char: 'X, looks: ALL[FALSE], format: NIL, comment: TRUE, endOfNode: FALSE, deltaLevel: 0, propList: NIL ]; PutRopeProp: PROC [key: ATOM, val: ROPE] ~ { tc.propList _ CONS[NEW[Atom.DottedPairNode _ [key: key, val: val]], tc.propList]; }; <> <> displayBox: MathBox.BOX _ NIL; displayExpr: MathDisplayExpr.DisplayExpr _ NIL; mathExpr: MathExpr.EXPR _ NIL; postfixValue, leading, topLeading, bottomLeading: ROPE _ NIL; -- for postfix properties IF exprRope=NIL THEN RETURN[FALSE]; <> mathExpr _ MathExpr.ExprFromRope[StripHeader[exprRope] ! MathExpr.parseError => {mathExpr _ MathConstructors.MakePlaceHolder[]; CONTINUE}]; <> displayExpr _ MathDisplayExpr.DisplayExprFromExpr[mathExpr]; <> displayBox _ displayExpr.Format[normal]; <> displayBox _ MathBox.Scale[displayBox, [pointSize, pointSize]]; <<>> <> <> <> leading _ Convert.RopeFromReal[displayBox.Height[]]; topLeading _ Convert.RopeFromReal[displayBox.Extents[].ascent + 12.0]; bottomLeading _ Convert.RopeFromReal[displayBox.Extents[].descent + 12.0]; postfixValue _ Rope.Cat[leading, " pt the leading 2 .copy .gt 3 1 .roll .ifelse leading "]; postfixValue _ Rope.Cat[postfixValue, topLeading, " pt the topLeading 2 .copy .gt 3 1 .roll .ifelse topLeading "]; postfixValue _ Rope.Cat[postfixValue, topLeading, " pt the topIndent 2 .copy .gt 3 1 .roll .ifelse topIndent "]; postfixValue _ Rope.Cat[postfixValue, bottomLeading, " pt the bottomLeading 2 .copy .gt 3 1 .roll .ifelse bottomLeading "]; <> <> PutRopeProp[$Postfix, postfixValue]; -- should this be on the Node ?? PutRopeProp[$Artwork, "MeddleExpr"]; PutRopeProp[$MeddleExpr, exprRope]; PutRopeProp[$MeddlePtSize, newPtSizeRope]; <> TiogaAccess.Put[writer, tc]; -- puts everything at once }; caminoItem: CaminoItem _ NARROW[clientData]; newPtSizeRope: ROPE _ ViewerTools.GetContents[caminoItem.scratchPadViewer]; -- get rope from ScratchPad (should be convertible to a REAL) newPtSize: REAL _ Convert.RealFromRope[newPtSizeRope]; selectionViewer: TiogaOps.Viewer _ TiogaOps.GetSelection[primary].viewer; location: TiogaOps.Location _ TiogaOps.GetSelection[primary].start; selection: TextEdit.RefTextNode _ location.node; exprRope: ROPE _ NARROW[TextEdit.GetCharProp[selection, location.where, $MeddleExpr]]; writer: TiogaAccess.Writer _ TiogaAccess.Create[]; locked: PROC [root: TextNode.Ref, tSel: TEditDocument.Selection] ~ { <> TiogaAccess.WriteSelection[writer]; -- replaces the primary selection }; IF WriteArtwork[writer: writer, pointSize: newPtSize] THEN { TEditInputOps.CallWithLocks[locked]; ViewerOps.PaintViewer[viewer: selectionViewer, hint: client]; }; }; <> Break: SIGNAL = CODE; EnterDebugger: Menus.MenuProc ~ { <> <<>> s: ExprViewerData _ NARROW[clientData]; expr: DisplayExpr _ s.displayExpr; SIGNAL Break; }; <> RegisterExprViewerClass[]; <> Commander.Register[key: "CaminoReal", proc: MakeCaminoItem, doc: "Create a new CaminoReal item" ]; <<>> <<[ ] _ MakeCaminoItem[NIL]; -- and create an instance>> <<>> <<>> END.