EditToolBuilderImpl.mesa
Copyright Ó 1985, 1986, 1987, 1991 by Xerox Corporation. All rights reserved.
Paxton on May 23, 1983 12:04 pm
McGregor on September 1, 1982 3:56 pm
Plass, April 15, 1983 12:53 pm
Russ Atkinson, September 26, 1983 5:55 pm
Russ Atkinson (RRA) June 18, 1985 1:21:44 pm PDT
Alison Lee June 11, 1986 5:08:14 pm PDT
Swinehart, November 14, 1986 9:59:13 am PST
Doug Wyatt, March 14, 1992 4:33 pm PST
Pier, January 7, 1989 2:08:52 pm PST
DIRECTORY
Buttons USING [Button, ButtonProc],
Containers USING [ChildXBound],
EditToolBuilder USING [Layout],
EditToolPrivate USING [editTool],
IO USING [atom, Close, EndOfStream, Error, GetInt, int, Put1, PutChar, RIS, RopeFromROS, ROS, STREAM],
Labels USING [Create, Label],
MBQueue,
MessageWindow USING [Append, Blink],
Rope USING [Map, ROPE],
Rules USING [Create, Rule],
TEditDocument USING [Selection, SelectionRec, TEditDocumentData],
TEditInput USING [CheckSelection],
TEditOps USING [GetSelData, SetTextContents],
TEditSelection USING [MakeSelection],
TextEdit USING [FetchLooks, Size],
TextEditBogus USING [GetRope],
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, TextEditBogus, TextNode, VFonts, ViewerOps, ViewerSpecs, ViewerTools
EXPORTS EditToolBuilder, EditToolPrivate
= {
Types
Layout: TYPE = EditToolBuilder.Layout;
ROPE: TYPE = Rope.ROPE;
STREAM: TYPE = IO.STREAM;
Global variables
queue: MBQueue.Queue ¬ MBQueue.Create[];
The synchronizing queue for the edit tool
ToNext:
PUBLIC
PROC [info: Layout, bigGap:
BOOL ¬
FALSE] = {
change entryLeft and heightSoFar to next "line" in container
info.entryLeft ¬ info.initLeft;
info.heightSoFar ¬ info.heightSoFar + info.entryHeight + info.entryVSpace;
IF bigGap THEN info.heightSoFar ¬ info.heightSoFar + info.entryVSpace/2;
};
HGap:
PUBLIC
PROC [info: Layout] =
--INLINE-- {
info.entryLeft ¬ info.entryLeft + info.gapSize };
VGap:
PUBLIC
PROC [info: Layout] =
--INLINE-- {
info.heightSoFar ¬ info.heightSoFar + info.entryVSpace };
ToMiddle:
PUBLIC
PROC [info: Layout] = {
change entryLeft to middle of container
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, 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, paint: FALSE];
entryLeft ¬ entryLeft + button.ww;
IF gapAfter THEN entryLeft ¬ entryLeft + gapSize;
RETURN[ button ];
};
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 ¬ TextEditBogus.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.Put1[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 {
end of string
PutChar[h, '"];
doingChars ¬ FALSE;
};
IF nospace THEN nospace ¬ FALSE ELSE PutChar[h,' ];
};
AddChar:
PROC [c:
CHARACTER] = {
IF ~doingChars
THEN {
start of string
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[]; Put1[h,atom[x]] };
x: REF INT => { Space[]; Put1[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] = {
[] ¬ LastHRule[ info, thickness, gapAbove, gapBelow ];
};
LastHRule:
PUBLIC
PROC [info: Layout, thickness:
CARDINAL ¬ 1, gapAbove, gapBelow:
BOOL ¬
TRUE]
RETURNS [rule: Rules.Rule] = {
OPEN info;
IF gapAbove THEN heightSoFar ¬ heightSoFar + entryVSpace*2;
rule ¬ 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;
RETURN[rule];
};
}.
..