<> <> <> <> <> <> <> <> <<>> DIRECTORY Buttons USING [Button, ButtonProc], Containers USING [ChildXBound], EditToolBuilder USING [Layout], EditToolPrivate USING [editTool], IO USING [atom, Close, EndOfStream, Error, GetInt, int, Put, PutChar, RIS, RopeFromROS, ROS, STREAM], Labels USING [Create, Label], MBQueue, MessageWindow USING [Append, Blink], Rope USING [Map, ROPE], Rules USING [Create], TEditDocument USING [Selection, SelectionRec, TEditDocumentData], TEditInput USING [CheckSelection], TEditOps USING [GetSelData, SetTextContents], TEditSelection USING [MakeSelection], TextEdit USING [FetchLooks, GetRope, Size], TextLooks USING [Looks, noLooks], TextNode USING [FirstChild, NarrowToTextNode, Offset, RefTextNode], VFonts USING [StringWidth], ViewerClasses USING [Viewer], ViewerOps USING [CreateViewer], ViewerSpecs USING [openRightWidth], ViewerTools USING [SetContents, SetSelection]; EditToolBuilderImpl: CEDAR PROGRAM IMPORTS Containers, EditToolPrivate, IO, Labels, MBQueue, MessageWindow, Rope, Rules, TEditInput, TEditOps, TEditSelection, TextEdit, TextNode, VFonts, ViewerOps, ViewerSpecs, ViewerTools EXPORTS EditToolBuilder, EditToolPrivate = { <> Layout: TYPE = EditToolBuilder.Layout; ROPE: TYPE = Rope.ROPE; STREAM: TYPE = IO.STREAM; <> queue: MBQueue.Queue _ MBQueue.Create[]; <> ToNext: PUBLIC PROC [info: Layout, bigGap: BOOL _ FALSE] = { <> info.entryLeft _ info.initLeft; info.heightSoFar _ info.heightSoFar + info.entryHeight + info.entryVSpace; IF bigGap THEN info.heightSoFar _ info.heightSoFar + info.entryVSpace/2; }; ToMiddle: PUBLIC PROC [info: Layout] = { <> info.entryLeft _ 190; }; BuildBox: PROC [info: Layout, proc: Buttons.ButtonProc, clientData: REF ANY _ NIL, fork: BOOL _ FALSE, gapAfter: BOOL _ TRUE, border: BOOL _ FALSE] RETURNS [button: Buttons.Button] = { OPEN info; button _ MBQueue.CreateButton[q: queue, info: [name: NIL, parent: container, wx: entryLeft, wy: heightSoFar+2, ww: entryHeight-2, wh: entryHeight-2, border: border], proc: proc, clientData: clientData, fork: fork, paint: FALSE]; entryLeft _ entryLeft + button.ww; IF gapAfter THEN entryLeft _ entryLeft + gapSize; }; BuildButton: PUBLIC PROC [info: Layout, name: ROPE, proc: Buttons.ButtonProc, clientData: REF ANY _ NIL, fork: BOOL _ FALSE, gapAfter: BOOL _ TRUE, border: BOOL _ FALSE] RETURNS [button: Buttons.Button] = { OPEN info; button _ MBQueue.CreateButton[q: queue, info: [name: name, parent: container, wx: entryLeft, wy: heightSoFar, border: border], proc: proc, clientData: clientData, fork: fork, paint: FALSE]; entryLeft _ entryLeft + button.ww; IF gapAfter THEN entryLeft _ entryLeft + gapSize; }; BuildLabel: PUBLIC PROC [info: Layout, name: ROPE, width: INTEGER _ 0] RETURNS [label: Labels.Label] = { OPEN info; label _ Labels.Create[info: [name: name, parent: container, border: FALSE, wx: entryLeft, wy: heightSoFar+1, ww: width, wh: entryHeight], paint: FALSE]; entryLeft _ entryLeft + label.ww; }; <<-------------------------->> BuildPair: PUBLIC PROC [info: Layout, proc: Buttons.ButtonProc, flag: BOOL, l1, l2: ROPE, clientData: REF ANY _ NIL, fork: BOOL _ FALSE] RETURNS [label: Labels.Label, button: Buttons.Button] = { OPEN info; w: INTEGER = MAX[ VFonts.StringWidth[l1], VFonts.StringWidth[l2]]; button _ BuildBox[info, proc, clientData, fork, FALSE, TRUE]; label _ BuildLabel[info, IF flag THEN l1 ELSE l2, w+15]; }; <<-------------------------->> BuildTriple: PUBLIC PROC [info: Layout, proc: Buttons.ButtonProc, state: [0..2], l0, l1, l2: ROPE, clientData: REF ANY _ NIL, fork: BOOL _ FALSE] RETURNS [label: Labels.Label, button: Buttons.Button] = { OPEN info; w: INTEGER = MAX[ VFonts.StringWidth[l0], VFonts.StringWidth[l1], VFonts.StringWidth[l2]]; labelRopes: ARRAY [0..2] OF ROPE = [l0,l1,l2]; button _ BuildBox[info, proc, clientData, fork, FALSE, TRUE]; label _ BuildLabel[info, labelRopes[state], w+15]; }; <<-------------------------->> DataFieldButton: PUBLIC PROC [arg: ViewerClasses.Viewer, clear: BOOL] = { IF clear THEN ViewerTools.SetContents[arg, NIL]; -- clear contents of field ViewerTools.SetSelection[arg, NIL]; -- make pending delete selection of field contents }; SavePSel: PUBLIC PROC = { IF ~EditToolPSel[] THEN prior^ _ TEditOps.GetSelData[]^; }; -- save it for later FixPSel: PUBLIC PROC = { -- if pSel is in data field, restore prior IF EditToolPSel[] AND TEditInput.CheckSelection[prior] THEN TEditSelection.MakeSelection[prior, primary]; }; EditToolPSel: PROC RETURNS [BOOL] = { pSel: TEditDocument.Selection = TEditOps.GetSelData[]; RETURN [pSel # NIL AND pSel.viewer # NIL AND pSel.viewer.parent=EditToolPrivate.editTool] }; prior: TEditDocument.Selection _ NEW [TEditDocument.SelectionRec]; BuildDataFieldPair: PUBLIC PROC [info: Layout, buttonRope: ROPE, buttonProc: Buttons.ButtonProc, clientData: REF ANY _ NIL, lines: CARDINAL _ 2] RETURNS [button: Buttons.Button, arg: ViewerClasses.Viewer] = { OPEN info; fudge: CARDINAL = 1; button _ BuildButton[info: info, name: buttonRope, proc: buttonProc, clientData: clientData, fork: FALSE, gapAfter: FALSE]; arg _ ViewerOps.CreateViewer[flavor: $Text, info: [parent: container, wx: entryLeft, wy: heightSoFar+fudge, ww: ViewerSpecs.openRightWidth-entryLeft-5, wh: entryHeight*lines, border: FALSE], paint: FALSE]; heightSoFar _ heightSoFar + entryHeight*lines; entryLeft _ initLeft; Containers.ChildXBound[container, arg]; }; <<-------------------------->> GetDataNode: PUBLIC PROC [arg: ViewerClasses.Viewer] RETURNS [TextNode.RefTextNode] = { WITH arg.data SELECT FROM tdd: TEditDocument.TEditDocumentData => RETURN [TextNode.NarrowToTextNode[TextNode.FirstChild[tdd.text]]]; ENDCASE => RETURN [NIL]; }; GetDataLooks: PUBLIC PROC [arg: ViewerClasses.Viewer, name: ROPE] RETURNS [looks: TextLooks.Looks] = { node: TextNode.RefTextNode _ GetDataNode[arg]; size: TextNode.Offset = TextEdit.Size[node]; IF size=0 THEN RETURN [TextLooks.noLooks]; looks _ TextEdit.FetchLooks[node,0]; FOR i: TextNode.Offset IN [1..size) DO IF TextEdit.FetchLooks[node,i]#looks THEN { OPEN MessageWindow; Append[name,TRUE]; Append[" does not have uniform looks. Using looks from first char."]; Blink[]; EXIT }; ENDLOOP; }; BadNumber: PUBLIC SIGNAL = CODE; GetInt: PUBLIC PROC [arg: ViewerClasses.Viewer] RETURNS [num: INT] = { rope: ROPE _ TextEdit.GetRope[GetDataNode[arg]]; h: STREAM _ IO.RIS[rope]; num _ IO.GetInt[h ! IO.Error, IO.EndOfStream => GOTO BadNum]; EXITS BadNum => SIGNAL BadNumber }; SetInt: PUBLIC PROC [arg: ViewerClasses.Viewer, num: INT] = { h: STREAM _ IO.ROS[]; IO.Put[h,IO.int[num]]; TEditOps.SetTextContents[arg, IO.RopeFromROS[h]]; }; ConvertList: PUBLIC PROC [list: LIST OF REF ANY] RETURNS [ROPE] = { OPEN IO; h: STREAM _ IO.ROS[]; doingChars: BOOL _ FALSE; nospace: BOOL _ TRUE; Space: PROC = { IF doingChars THEN { <> PutChar[h, '"]; doingChars _ FALSE; }; IF nospace THEN nospace _ FALSE ELSE PutChar[h,' ]; }; AddChar: PROC [c: CHARACTER] = { IF ~doingChars THEN { <> Space[]; PutChar[h, '"]; doingChars _ TRUE }; SELECT c FROM '', '", '\\ => PutChar[h, '\\]; ENDCASE; PutChar[h, c] }; { ENABLE UNWIND => h.Close[]; FOR l: LIST OF REF ANY _ list, l.rest UNTIL l=NIL DO WITH l.first SELECT FROM x: ATOM => { Space[]; Put[h,atom[x]] }; x: REF INT => { Space[]; Put[h,int[x^]] }; x: REF CHARACTER => AddChar[x^]; x: ROPE => { AddC: SAFE PROC [c: CHAR] RETURNS [BOOL] = { AddChar[c]; RETURN [FALSE]; }; [] _ Rope.Map[base: x, action: AddC] }; x: REF TEXT => { FOR i: NAT IN [0..x.length) DO AddChar[x[i]]; ENDLOOP; }; ENDCASE; ENDLOOP; IF doingChars THEN PutChar[h, '"]; RETURN [IO.RopeFromROS[h]]; }; }; <<-------------------------->> HRule: PUBLIC PROC [info: Layout, thickness: CARDINAL _ 1, gapAbove, gapBelow: BOOL _ TRUE] = { OPEN info; IF gapAbove THEN heightSoFar _ heightSoFar + entryVSpace*2; [] _ Rules.Create[info: [parent: container, wx: 0, wy: heightSoFar, ww: ViewerSpecs.openRightWidth, wh: thickness], paint: FALSE]; heightSoFar _ heightSoFar + thickness; IF gapBelow THEN heightSoFar _ heightSoFar + entryVSpace*2; }; }. ..