EditToolMiscImpl.mesa
Copyright Ó 1982, 1983, 1984, 1985, 1986, 1991, 1992 by Xerox Corporation. All rights reserved.
Michael Plass, May 9, 1986 1:54:42 pm PDT
Rick Beach, May 28, 1985 1:54:05 pm PDT
Russ Atkinson (RRA) June 18, 1985 4:58:04 pm PDT
Alison Lee June 11, 1986 10:32:02 pm PDT
Swinehart, November 14, 1986 10:01:06 am PST
Doug Wyatt, March 14, 1992 5:55 pm PST
DIRECTORY
Atom USING [GetPName, MakeAtom],
Buttons USING [ButtonProc],
CharOps USING [XAlphaNumeric, XBlank],
EditToolBuilder USING [BuildButton, BuildDataFieldPair, BuildPair, BuildTriple, DataFieldButton, GetDataNode, HGap, ToMiddle, ToNext, VGap],
EditToolPrivate,
Labels USING [Set],
MessageWindow USING [Append, Blink],
NodeProps,
NodeStyleOps USING [StyleNameForNode],
Process USING [Detach],
Rope USING [Concat, Equal, ROPE, Substr],
RuntimeError USING [UNCAUGHT],
TEditDocument USING [Selection, SelectionPoint],
TEditInput USING [CommandProc, CurrentEvent],
TEditInputOps USING [CheckReadonly, LoadAbbreviations, ReloadStyleName, SetStyleName, SetFormatName],
TEditLocks USING [Lock],
TEditOps USING [GetSelData, SetTextContents],
TEditSelection USING [LockSel, pSel, SelectionRoot, UnlockDocAndPSel, UnlockSel],
TextEdit,
TextNode USING [NodeItself, Ref, Root, StepForward],
ViewerClasses USING [Viewer],
ViewerOps USING [EnumerateChildren, EnumerateViewers, PaintViewer];
EditToolMiscImpl: CEDAR PROGRAM
IMPORTS Atom, CharOps, EditToolBuilder, EditToolPrivate, Labels, MessageWindow, NodeProps, NodeStyleOps, Process, Rope, RuntimeError, TEditInput, TEditInputOps, TEditLocks, TEditOps, TEditSelection, TextEdit, TextNode, ViewerOps
EXPORTS EditToolPrivate
= BEGIN
ROPE: TYPE ~ Rope.ROPE;
BuildPropertyButtons
BuildRealPropertyButtons: PUBLIC PROC [info: EditToolPrivate.Info] = {
[, info.propNameArg] ¬ EditToolBuilder.BuildDataFieldPair[info.layout, "PropName:", PropNameArgButton, info, 1];
EditToolBuilder.VGap[info.layout];
[, info.propValueArg] ¬ EditToolBuilder.BuildDataFieldPair[info.layout, "PropValue:", PropValueArgButton, info, 1];
EditToolBuilder.VGap[info.layout];
info.propNode ¬ forSelectedNodes;
[] ¬ EditToolBuilder.BuildButton[info.layout, "GetNodeProp", GetPropButton, info];
[] ¬ EditToolBuilder.BuildButton[info.layout, "SetNodeProp", SetPropButton, info];
[] ¬ EditToolBuilder.BuildButton[info.layout, "RemoveNodeProp", RemovePropButton, info];
[] ¬ EditToolBuilder.BuildButton[info.layout, "ListNodeProps", ListPropsButton, info];
EditToolBuilder.ToNext[info.layout];
EditToolBuilder.ToMiddle[info.layout];
propRootNameRope ¬ "PropForRoot";
propSelectionNameRope ¬ "PropForSelection";
propSelectedCharsNameRope ¬ "PropForSelectedCharacter";
[info.propNodeLabel, ] ¬ EditToolBuilder.BuildTriple[info.layout, PropNodeButton, ORD[info.propNode], propRootNameRope,propSelectionNameRope, propSelectedCharsNameRope, info];
EditToolBuilder.ToNext[info.layout];
[] ¬ EditToolBuilder.BuildButton[info.layout, "FindNodeProp", FindPropButton, info];
EditToolBuilder.HGap[info.layout];
[, info.propPatternArg] ¬ EditToolBuilder.BuildDataFieldPair[info.layout, "PropPattern:", PropPatternArgButton, info, 1];
};
BuildPropertyButtons: PUBLIC PROC [info: EditToolPrivate.Info] = {
[, info.propNameArg] ¬ EditToolBuilder.BuildDataFieldPair[info.layout, "Property name:", PropNameArgButton, info, 1];
EditToolBuilder.VGap[info.layout];
[, info.propValueArg] ¬ EditToolBuilder.BuildDataFieldPair[info.layout, "Property value:", PropValueArgButton, info, 1];
EditToolBuilder.VGap[info.layout];
info.propNode ¬ forSelectedNodes;
[] ¬ EditToolBuilder.BuildButton[info.layout, "Get", GetPropButton, info];
[] ¬ EditToolBuilder.BuildButton[info.layout, "Set", SetPropButton, info];
[] ¬ EditToolBuilder.BuildButton[info.layout, "Remove", RemovePropButton, info];
[] ¬ EditToolBuilder.BuildButton[info.layout, "List", ListPropsButton, info];
EditToolBuilder.ToMiddle[info.layout];
propRootNameRope ¬ "For root node";
propSelectionNameRope ¬ "For selected nodes";
propSelectedCharsNameRope ¬ "For selected characters";
[info.propNodeLabel, ] ¬ EditToolBuilder.BuildTriple[info.layout, PropNodeButton, ORD[info.propNode], propRootNameRope,propSelectionNameRope, propSelectedCharsNameRope, info];
EditToolBuilder.ToNext[info.layout];
[] ¬ EditToolBuilder.BuildButton[info.layout, "Find", FindPropButton, info];
EditToolBuilder.HGap[info.layout];
[, info.propPatternArg] ¬ EditToolBuilder.BuildDataFieldPair[info.layout, "Value pattern:", PropPatternArgButton, info, 1];
};
BuildStyleButtons
BuildRealStyleButtons: PUBLIC PROC [info: EditToolPrivate.Info] = {
[, info.styleNameArg] ¬ EditToolBuilder.BuildDataFieldPair[info.layout, "Style name:", StyleNameArgButton, info, 1];
EditToolBuilder.VGap[info.layout];
info.styleNode ¬ forRoot;
[] ¬ EditToolBuilder.BuildButton[info.layout, "GetNodeStyleName", GetStyleNameButton, info];
[] ¬ EditToolBuilder.BuildButton[info.layout, "SetNodeStyleName", SetStyleNameButton, info];
[] ¬ EditToolBuilder.BuildButton[info.layout, "ClearNodeStyleName", ClearStyleNameButton, info];
EditToolBuilder.ToNext[info.layout];
EditToolBuilder.ToMiddle[info.layout];
styleSelectionNameRope ¬ "StyleNameForSelection";
styleRootNameRope ¬ "StyleNameForRoot";
[info.styleNodeLabel, ] ¬ EditToolBuilder.BuildPair[info.layout, StyleNameNodeButton, info.styleNode=forSelectedNodes, styleSelectionNameRope, styleRootNameRope, info];
EditToolBuilder.ToNext[info.layout];
[] ¬ EditToolBuilder.BuildButton[info.layout, "LoadStyleDefinition", LoadStyleButton, info];
[] ¬ EditToolBuilder.BuildButton[info.layout, "LoadAbbreviations", LoadAbbreviationsButton, info];
};
BuildStyleButtons: PUBLIC PROC [info: EditToolPrivate.Info] = {
[, info.styleNameArg] ¬ EditToolBuilder.BuildDataFieldPair[info.layout, "Style name:", StyleNameArgButton, info, 1];
EditToolBuilder.VGap[info.layout];
info.styleNode ¬ forRoot;
[] ¬ EditToolBuilder.BuildButton[info.layout, "Get", GetStyleNameButton, info];
[] ¬ EditToolBuilder.BuildButton[info.layout, "Set", SetStyleNameButton, info];
[] ¬ EditToolBuilder.BuildButton[info.layout, "Clear", ClearStyleNameButton, info];
EditToolBuilder.ToMiddle[info.layout];
styleSelectionNameRope ¬ "For selected nodes";
styleRootNameRope ¬ "For root node";
[info.styleNodeLabel, ] ¬ EditToolBuilder.BuildPair[info.layout, StyleNameNodeButton, info.styleNode=forSelectedNodes, styleSelectionNameRope, styleRootNameRope, info];
EditToolBuilder.ToNext[info.layout];
[] ¬ EditToolBuilder.BuildButton[info.layout, "LoadStyleDefinition", LoadStyleButton, info];
[] ¬ EditToolBuilder.BuildButton[info.layout, "LoadAbbreviations", LoadAbbreviationsButton, info];
};
BuildFormatButtons
BuildFormatButtons: PUBLIC PROC [info: EditToolPrivate.Info] = {
[, info.formatNameArg] ¬ EditToolBuilder.BuildDataFieldPair[info.layout, "Format name:", FormatNameArgButton, info, 1];
EditToolBuilder.VGap[info.layout];
info.formatNode ¬ forSelectedNodes;
[] ¬ EditToolBuilder.BuildButton[info.layout, "Get", GetFormatNameButton, info];
[] ¬ EditToolBuilder.BuildButton[info.layout, "Set", SetFormatNameButton, info];
[] ¬ EditToolBuilder.BuildButton[info.layout, "Clear", ClearFormatNameButton, info];
EditToolBuilder.ToMiddle[info.layout];
formatSelectionNameRope ¬ "For selected nodes";
formatRootNameRope ¬ "For root node";
[info.formatNodeLabel, ] ¬ EditToolBuilder.BuildPair[info.layout, FormatNameNodeButton, info.formatNode=forSelectedNodes, formatSelectionNameRope, formatRootNameRope, info];
};
BuildRealFormatButtons: PUBLIC PROC [info: EditToolPrivate.Info] = {
[, info.formatNameArg] ¬ EditToolBuilder.BuildDataFieldPair[info.layout, "Format name:", FormatNameArgButton, info, 1];
EditToolBuilder.VGap[info.layout];
info.formatNode ¬ forSelectedNodes;
[] ¬ EditToolBuilder.BuildButton[info.layout, "GetNodeFormatName", GetFormatNameButton, info];
[] ¬ EditToolBuilder.BuildButton[info.layout, "SetNodeFormatName", SetFormatNameButton, info];
[] ¬ EditToolBuilder.BuildButton[info.layout, "ClearNodeFormatName", ClearFormatNameButton, info];
EditToolBuilder.ToNext[info.layout];
EditToolBuilder.ToMiddle[info.layout];
formatSelectionNameRope ¬ "FormatNameForSelection";
formatRootNameRope ¬ "FormatNameForRoot";
[info.formatNodeLabel, ] ¬ EditToolBuilder.BuildPair[info.layout, FormatNameNodeButton, info.formatNode=forSelectedNodes, formatSelectionNameRope, formatRootNameRope, info];
};
GetNameArg
BadArg: PUBLIC ERROR = CODE;
GetNameArg: PUBLIC PROC [arg: ViewerClasses.Viewer] RETURNS [ROPE] = {
node: TextNode.Ref ~ EditToolBuilder.GetDataNode[arg];
size: INT ~ TextEdit.Size[node];
start, end: INT ¬ size;
FOR i: INT IN[0..size) DO
IF NOT CharOps.XBlank[TextEdit.FetchChar[node, i]] THEN { start ¬ i; EXIT };
ENDLOOP;
FOR i: INT IN[start..size) DO
IF NOT CharOps.XAlphaNumeric[TextEdit.FetchChar[node, i]] THEN { end ¬ i; EXIT };
ENDLOOP;
FOR i: INT IN[end..size) DO
IF NOT CharOps.XBlank[TextEdit.FetchChar[node, i]] THEN GOTO Bad;
ENDLOOP;
IF end>start THEN RETURN[Rope.Substr[node.rope, start, end-start]] ELSE GOTO Bad;
EXITS Bad => {
MessageWindow.Append["Enter name consisting of one or more alphanumeric characters.", TRUE];
MessageWindow.Blink[];
ERROR BadArg;
};
};
GetRopeArg: PUBLIC PROC [arg: ViewerClasses.Viewer] RETURNS [ROPE] = {
node: TextNode.Ref ~ EditToolBuilder.GetDataNode[arg];
size: INT ~ TextEdit.Size[node];
FOR i: INT IN[0..size) DO
IF NOT Char.Set[TextEdit.FetchChar[node, i]]=0 THEN GOTO Bad;
ENDLOOP;
RETURN[node.rope];
EXITS Bad => {
MessageWindow.Append["Enter value consisting only of 8-bit characters.", TRUE];
MessageWindow.Blink[];
ERROR BadArg;
};
};
ForEachNode: PROC [nodeKind: EditToolPrivate.NodeKind, pSel: TEditDocument.Selection,
proc: PROC [node: TextNode.Ref, start: INT, size: INT]] = {
SELECT nodeKind FROM
forRoot => proc[TextNode.Root[pSel.start.pos.node], 0, 0];
forSelectedNodes, forSelectedChars => {
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;
};
ENDCASE => ERROR
};
SetNodeName: PROC [info: EditToolPrivate.Info, name: ROPE, style: BOOLEAN,
pSel: TEditDocument.Selection] = {
Set: PROC [node: TextNode.Ref, start: INT, size: INT] = {
IF style THEN TEditInputOps.SetStyleName[name, node]
ELSE TEditInputOps.SetFormatName[name, node]
};
ForEachNode[IF style THEN info.styleNode ELSE info.formatNode, pSel, Set]
};
StyleNameArg
styleNameArgAtom: LIST OF REF =
EditToolPrivate.Register[$StyleName, StyleNameArgOp];
clearStyleNameArgAtom: LIST OF REF =
EditToolPrivate.Register[$ClearStyleName, ClearStyleNameArgOp];
StyleNameArgButton: Buttons.ButtonProc = {
EditToolPrivate.DoButton[styleNameArgAtom, clearStyleNameArgAtom, mouseButton=red]
};
StyleNameArgOp: TEditInput.CommandProc = {
EditToolBuilder.DataFieldButton[EditToolPrivate.mainToolInfo.styleNameArg, FALSE]
};
ClearStyleNameArgOp: TEditInput.CommandProc = {
EditToolBuilder.DataFieldButton[EditToolPrivate.mainToolInfo.styleNameArg, TRUE]
};
FormatNameArg
formatNameArgAtom: LIST OF REF =
EditToolPrivate.Register[$FormatName, FormatNameArgOp];
typeNameArgAtom: LIST OF REF =
EditToolPrivate.Register[$TypeName, FormatNameArgOp];
clearFormatNameArgAtom: LIST OF REF =
EditToolPrivate.Register[$ClearFormatName, ClearFormatNameArgOp];
clearTypeNameArgAtom: LIST OF REF =
EditToolPrivate.Register[$ClearTypeName, ClearFormatNameArgOp];
FormatNameArgButton: Buttons.ButtonProc = {
EditToolPrivate.DoButton[formatNameArgAtom, clearFormatNameArgAtom, mouseButton=red]
};
FormatNameArgOp: TEditInput.CommandProc = {
EditToolBuilder.DataFieldButton[EditToolPrivate.mainToolInfo.formatNameArg, FALSE]
};
ClearFormatNameArgOp: TEditInput.CommandProc = {
EditToolBuilder.DataFieldButton[EditToolPrivate.mainToolInfo.formatNameArg, TRUE]
};
GetStyleName
getStyleNameAtom: LIST OF REF =
EditToolPrivate.Register[$GetNodeStyleName, GetStyleNameOp];
GetStyleNameButton: Buttons.ButtonProc = {
EditToolPrivate.DoButton[getStyleNameAtom]
};
GetStyleNameOp: TEditInput.CommandProc = {
GetStyleNameCom[EditToolPrivate.mainToolInfo];
};
GetStyleNameCom: PROC [info: EditToolPrivate.Info] = {
GetNameCom[info, TRUE];
};
getFormatNameAtom: LIST OF REF =
EditToolPrivate.Register[$GetNodeFormatName, GetFormatNameOp];
getTypeNameAtom: LIST OF REF =
EditToolPrivate.Register[$GetNodeTypeName, GetFormatNameOp];
GetFormatNameButton: Buttons.ButtonProc = {
EditToolPrivate.DoButton[getFormatNameAtom]
};
GetFormatNameOp: TEditInput.CommandProc = {
GetFormatNameCom[EditToolPrivate.mainToolInfo];
};
GetFormatNameCom: PROC [info: EditToolPrivate.Info] = {
GetNameCom[info, FALSE];
};
NotUniform: SIGNAL = CODE;
GetNameCom: PROC [info: EditToolPrivate.Info, style: BOOLEAN] = {
pSel: TEditDocument.Selection = TEditOps.GetSelData[];
nodeKind: EditToolPrivate.NodeKind ¬ IF style THEN info.styleNode ELSE info.formatNode;
name: ATOM ¬ NIL;
arg: ViewerClasses.Viewer ¬ IF style THEN info.styleNameArg ELSE info.formatNameArg;
Get: PROC [node: TextNode.Ref, start, size: INT] = {
n: ATOM ¬ IF style THEN NodeStyleOps.StyleNameForNode[node]
ELSE TextEdit.GetFormat[node];
IF name = NIL THEN name ¬ n
ELSE IF name # n THEN {
MessageWindow.Append[IF style
THEN "Nodes don't have uniform style. Using first."
ELSE "Nodes don't have uniform format. Using first.",
TRUE];
MessageWindow.Blink[];
SIGNAL NotUniform;
}
};
IF NOT EditToolPrivate.CheckPSel[pSel] THEN RETURN;
ForEachNode[nodeKind, pSel, Get ! NotUniform => CONTINUE];
TEditOps.SetTextContents[arg, IF name=NIL THEN NIL ELSE Atom.GetPName[name]];
};
SetStyleName
setStyleNameAtom: LIST OF REF =
EditToolPrivate.Register[$SetNodeStyleName, SetStyleNameOp];
SetStyleNameButton: Buttons.ButtonProc = {
EditToolPrivate.DoButton[setStyleNameAtom]
};
SetStyleNameOp: TEditInput.CommandProc = {
SetStyleNameCom[EditToolPrivate.mainToolInfo];
};
SetStyleNameCom: PROC [info: EditToolPrivate.Info] = {
SetNameCom[info, TRUE];
};
setFormatNameAtom: LIST OF REF =
EditToolPrivate.Register[$SetNodeFormatName, SetFormatNameOp];
setTypeNameAtom: LIST OF REF =
EditToolPrivate.Register[$SetNodeTypeName, SetFormatNameOp];
SetFormatNameButton: Buttons.ButtonProc = {
EditToolPrivate.DoButton[setFormatNameAtom]
};
SetFormatNameOp: TEditInput.CommandProc = {
SetFormatNameCom[EditToolPrivate.mainToolInfo];
};
SetFormatNameCom: PROC [info: EditToolPrivate.Info] = {
SetNameCom[info, FALSE];
};
SetNameCom: PROC [info: EditToolPrivate.Info, style: BOOLEAN] = {
pSel: TEditDocument.Selection;
arg: ViewerClasses.Viewer ¬ IF style THEN info.styleNameArg ELSE info.formatNameArg;
name: ROPE ¬ GetNameArg[arg ! BadArg => GOTO Bad];
TEditSelection.LockSel[primary, "SetNameCom"];
pSel ¬ TEditOps.GetSelData[];
IF NOT EditToolPrivate.CheckPSel[pSel] OR NOT TEditInputOps.CheckReadonly[pSel] THEN {
TEditSelection.UnlockSel[primary];
RETURN;
};
SetNodeName[info, name, style, pSel];
TEditSelection.UnlockSel[primary];
EXITS Bad => RETURN
};
ClearFormat
clearFormatNameAtom: LIST OF REF =
EditToolPrivate.Register[$ClearNodeFormatName, ClearFormatNameOp];
clearTypeNameAtom: LIST OF REF =
EditToolPrivate.Register[$ClearNodeTypeName, ClearFormatNameOp];
ClearFormatNameButton: Buttons.ButtonProc = {
EditToolPrivate.DoButton[clearFormatNameAtom]
};
ClearFormatNameOp: TEditInput.CommandProc = {
ClearFormatNameCom[EditToolPrivate.mainToolInfo];
};
ClearFormatNameCom: PROC [info: EditToolPrivate.Info] = {
pSel: TEditDocument.Selection = TEditOps.GetSelData[];
IF NOT EditToolPrivate.CheckPSel[pSel] THEN RETURN;
IF NOT TEditInputOps.CheckReadonly[pSel] THEN RETURN;
SetNodeName[info, NIL, FALSE, pSel]
};
clearStyleNameAtom: LIST OF REF =
EditToolPrivate.Register[$ClearNodeStyleName, ClearStyleNameOp];
ClearStyleNameButton: Buttons.ButtonProc = {
EditToolPrivate.DoButton[clearStyleNameAtom]
};
ClearStyleNameOp: TEditInput.CommandProc = {
ClearStyleNameCom[EditToolPrivate.mainToolInfo];
};
ClearStyleNameCom: PROC [info: EditToolPrivate.Info] = {
pSel: TEditDocument.Selection = TEditOps.GetSelData[];
IF NOT EditToolPrivate.CheckPSel[pSel] THEN RETURN;
IF NOT TEditInputOps.CheckReadonly[pSel] THEN RETURN;
SetNodeName[info, NIL, TRUE, pSel]
};
LoadStyle
loadStyleAtom: LIST OF REF =
EditToolPrivate.Register[$LoadStyleDefinition, LoadStyleOp];
LoadStyleButton: Buttons.ButtonProc = {
EditToolPrivate.DoButton[loadStyleAtom]
};
LoadStyleOp: TEditInput.CommandProc = {
LoadStyle[EditToolPrivate.mainToolInfo];
};
LoadStyle: PROC [info: EditToolPrivate.Info] = {
repaint: PROC [v: ViewerClasses.Viewer] RETURNS [BOOL ¬ TRUE] = {
SELECT v.class.flavor FROM
$Text => TRUSTED {Process.Detach[FORK ViewerOps.PaintViewer[v, all]]};
$Container => ViewerOps.EnumerateChildren[v, repaint];
ENDCASE;
RETURN [TRUE]
};
name: ROPE ¬ GetNameArg[info.styleNameArg ! BadArg => GOTO Bad];
TEditInputOps.ReloadStyleName[name];
ViewerOps.EnumerateViewers[repaint];
EXITS Bad => RETURN
};
LoadAbbreviations
loadAbbreviationsAtom: LIST OF REF =
EditToolPrivate.Register[$LoadAbbreviations, LoadAbbreviationsOp];
LoadAbbreviationsButton: Buttons.ButtonProc = {
EditToolPrivate.DoButton[loadAbbreviationsAtom]
};
LoadAbbreviationsOp: TEditInput.CommandProc = {
LoadAbbreviations[EditToolPrivate.mainToolInfo];
};
LoadAbbreviations: PROC [info: EditToolPrivate.Info] = {
name: ROPE ¬ GetNameArg[info.styleNameArg ! BadArg => GOTO Bad];
TEditInputOps.LoadAbbreviations[name];
EXITS Bad => RETURN
};
Format/Style name ranges
styleRootNameRope: ROPE;
formatRootNameRope: ROPE;
propRootNameRope: ROPE;
styleSelectionNameRope: ROPE;
formatSelectionNameRope: ROPE;
propSelectionNameRope: ROPE;
propSelectedCharsNameRope: ROPE;
rootFormatNameAtom: LIST OF REF =
EditToolPrivate.Register[$FormatNameForRoot, RootFormatNameOp];
rootTypeNameAtom: LIST OF REF =
EditToolPrivate.Register[$TypeNameForRoot, RootFormatNameOp];
selFormatNameAtom: LIST OF REF =
EditToolPrivate.Register[$FormatNameForSelection, SelectionFormatNameOp];
selTypeNameAtom: LIST OF REF =
EditToolPrivate.Register[$TypeNameForSelection, SelectionFormatNameOp];
FormatNameNodeButton: Buttons.ButtonProc = {
EditToolPrivate.ChangeState[EditToolPrivate.mainToolInfo.formatNode=forSelectedNodes, selFormatNameAtom, rootFormatNameAtom]
};
RootFormatNameOp: TEditInput.CommandProc = {
RootFormatName[EditToolPrivate.mainToolInfo];
};
RootFormatName: PROC [info: EditToolPrivate.Info] = {
info.formatNode ¬ forRoot;
Labels.Set[info.formatNodeLabel, formatRootNameRope]
};
SelectionFormatNameOp: TEditInput.CommandProc = {
SelectionFormatName[EditToolPrivate.mainToolInfo];
};
SelectionFormatName: PROC [info: EditToolPrivate.Info] = {
info.formatNode ¬ forSelectedNodes;
Labels.Set[info.formatNodeLabel, formatSelectionNameRope]
};
rootStyleNameAtom: LIST OF REF =
EditToolPrivate.Register[$StyleNameForRoot, RootStyleNameOp];
selStyleNameAtom: LIST OF REF =
EditToolPrivate.Register[$StyleNameForSelection, SelectionStyleNameOp];
StyleNameNodeButton: Buttons.ButtonProc = {
EditToolPrivate.ChangeState[EditToolPrivate.mainToolInfo.styleNode=forSelectedNodes, selStyleNameAtom, rootStyleNameAtom]
};
RootStyleNameOp: TEditInput.CommandProc = {
RootStyleName[EditToolPrivate.mainToolInfo];
};
RootStyleName: PROC [info: EditToolPrivate.Info] = {
info.styleNode ¬ forRoot;
Labels.Set[info.styleNodeLabel, styleRootNameRope]
};
SelectionStyleNameOp: TEditInput.CommandProc = {
SelectionStyleName[EditToolPrivate.mainToolInfo];
};
SelectionStyleName: PROC [info: EditToolPrivate.Info] = {
info.styleNode ¬ forSelectedNodes;
Labels.Set[info.styleNodeLabel, styleSelectionNameRope]
};
PropName
propNameArgAtom: LIST OF REF =
EditToolPrivate.Register[$PropName, PropNameArgOp];
clearPropNameArgAtom: LIST OF REF =
EditToolPrivate.Register[$ClearPropName, ClearPropNameArgOp];
PropNameArgButton: Buttons.ButtonProc = {
EditToolPrivate.DoButton[propNameArgAtom, clearPropNameArgAtom, mouseButton=red]
};
PropNameArgOp: TEditInput.CommandProc = {
PropNameArg[EditToolPrivate.mainToolInfo];
};
PropNameArg: PROC [info: EditToolPrivate.Info] = {
EditToolBuilder.DataFieldButton[info.propNameArg, FALSE];
};
ClearPropNameArgOp: TEditInput.CommandProc = {
ClearPropNameArg[EditToolPrivate.mainToolInfo];
};
ClearPropNameArg: PROC [info: EditToolPrivate.Info] = {
EditToolBuilder.DataFieldButton[info.propNameArg, TRUE];
};
PropValue
propValueArgAtom: LIST OF REF =
EditToolPrivate.Register[$PropValue, PropValueArgOp];
clearPropValueArgAtom: LIST OF REF =
EditToolPrivate.Register[$ClearPropValue, ClearPropValueArgOp];
PropValueArgButton: Buttons.ButtonProc = {
EditToolPrivate.DoButton[propValueArgAtom, clearPropValueArgAtom, mouseButton=red]
};
PropValueArgOp: TEditInput.CommandProc = {
PropValueArg[EditToolPrivate.mainToolInfo];
};
PropValueArg: PROC [info: EditToolPrivate.Info] = {
EditToolBuilder.DataFieldButton[info.propValueArg, FALSE]
};
ClearPropValueArgOp: TEditInput.CommandProc = {
ClearPropValueArg[EditToolPrivate.mainToolInfo]
};
ClearPropValueArg: PROC [info: EditToolPrivate.Info] = {
EditToolBuilder.DataFieldButton[info.propValueArg, TRUE]
};
PropPatternArg
propPatternArgAtom: LIST OF REF =
EditToolPrivate.Register[$PropPattern, PropPatternArgOp];
clearPropPatternArgAtom: LIST OF REF =
EditToolPrivate.Register[$ClearPropPattern, ClearPropPatternArgOp];
PropPatternArgButton: Buttons.ButtonProc = {
EditToolPrivate.DoButton[propPatternArgAtom, clearPropPatternArgAtom, mouseButton=red]
};
PropPatternArgOp: TEditInput.CommandProc = {
PropPatternArg[EditToolPrivate.mainToolInfo]
};
PropPatternArg: PROC [info: EditToolPrivate.Info] = {
EditToolBuilder.DataFieldButton[info.propPatternArg, FALSE]
};
ClearPropPatternArgOp: TEditInput.CommandProc = {
ClearPropPatternArg[EditToolPrivate.mainToolInfo]
};
ClearPropPatternArg: PROC [info: EditToolPrivate.Info] = {
EditToolBuilder.DataFieldButton[info.propPatternArg, TRUE]
};
PropNode
rootPropAtom: LIST OF REF =
EditToolPrivate.Register[$PropForRoot, RootPropOp];
selPropAtom: LIST OF REF =
EditToolPrivate.Register[$PropForSelection, SelectionPropOp];
charPropAtom: LIST OF REF =
EditToolPrivate.Register[$PropForSelectedCharacter, CharacterPropOp];
PropNodeButton: Buttons.ButtonProc = {
EditToolPrivate.CycleTriple[ORD[EditToolPrivate.mainToolInfo.propNode], rootPropAtom, selPropAtom, charPropAtom]
};
RootPropOp: TEditInput.CommandProc = {
RootProp[EditToolPrivate.mainToolInfo];
};
RootProp: PROC [info: EditToolPrivate.Info] = {
info.propNode ¬ forRoot;
Labels.Set[info.propNodeLabel, propRootNameRope]
};
SelectionPropOp: TEditInput.CommandProc = {
SelectionProp[EditToolPrivate.mainToolInfo];
};
SelectionProp: PROC [info: EditToolPrivate.Info] = {
info.propNode ¬ forSelectedNodes;
Labels.Set[info.propNodeLabel, propSelectionNameRope]
};
CharacterPropOp: TEditInput.CommandProc = {
SelectedCharsProp[EditToolPrivate.mainToolInfo];
};
SelectedCharsProp: PROC [info: EditToolPrivate.Info] = {
info.propNode ¬ forSelectedChars;
Labels.Set[info.propNodeLabel, propSelectedCharsNameRope]
};
GetProp
getPropAtom: LIST OF REF =
EditToolPrivate.Register[$GetNodeProp, GetPropOp];
GetPropButton: Buttons.ButtonProc = {
EditToolPrivate.DoButton[getPropAtom]
};
GetPropOp: TEditInput.CommandProc = {
GetPropCom[EditToolPrivate.mainToolInfo];
};
GetPropCom: PROC [info: EditToolPrivate.Info] = {
pSel: TEditDocument.Selection;
root: TextNode.Ref;
name: ROPE;
key: ATOM;
valueRope: ROPE;
haveFirst: BOOLEAN ¬ FALSE;
SaveOrCheck: PROC [value: REF] ~ {
vrope: ROPE ¬ NodeProps.GetSpecs[key, value];
IF haveFirst THEN {
IF NOT Rope.Equal[valueRope, vrope] THEN {
MessageWindow.Append[IF info.propNode = forSelectedChars THEN "Characters" ELSE "Nodes", TRUE];
MessageWindow.Append[" don't have uniform property values. Using first.", FALSE];
MessageWindow.Blink[];
SIGNAL NotUniform;
};
}
ELSE {
valueRope ¬ vrope;
haveFirst ¬ TRUE;
};
};
Get: PROC [node: TextNode.Ref, start, size: INT] = {
IF info.propNode = forSelectedChars THEN {
IF node.charProps#NIL THEN FOR i: INT IN [start..start+size) DO
SaveOrCheck[TextEdit.GetCharProp[node, i, key]];
ENDLOOP;
}
ELSE SaveOrCheck[TextEdit.GetProp[node, key]];
};
name ¬ GetNameArg[info.propNameArg ! BadArg => GOTO Bad];
key ¬ Atom.MakeAtom[name];
TEditSelection.LockSel[primary, "GetPropCom"];
pSel ¬ TEditOps.GetSelData[];
IF NOT EditToolPrivate.CheckPSel[pSel] THEN {
TEditSelection.UnlockSel[primary];
RETURN;
};
root ¬ TEditSelection.SelectionRoot[pSel];
[] ¬ TEditLocks.Lock[root, "GetPropCom", read];
ForEachNode[info.propNode, pSel, Get ! NotUniform => CONTINUE];
TEditSelection.UnlockDocAndPSel[root];
TEditOps.SetTextContents[info.propValueArg, valueRope];
EXITS Bad => RETURN
};
SetProp
setPropAtom: LIST OF REF =
EditToolPrivate.Register[$SetNodeProp, SetPropOp];
SetPropButton: Buttons.ButtonProc = {
EditToolPrivate.DoButton[setPropAtom]
};
SetPropOp: TEditInput.CommandProc = {
SetPropCom[EditToolPrivate.mainToolInfo];
};
SetPropCom: PROC [info: EditToolPrivate.Info] = {
pSel: TEditDocument.Selection;
name, valueRope: ROPE;
key: ATOM;
root: TextNode.Ref;
Put: PROC [node: TextNode.Ref, start, size: INT] = {
value: REF ~ NodeProps.DoSpecs[key, valueRope];
IF info.propNode = forSelectedChars THEN
TextEdit.PutCharProp[node: node, index: start, name: key, value: value, nChars: size, event: TEditInput.CurrentEvent[], root: root]
ELSE {
IF NodeProps.Is[key, $ClientOnly]
THEN {
MessageWindow.Append["Can't change ", TRUE];
MessageWindow.Append[Atom.GetPName[key], FALSE];
MessageWindow.Append[" node property with the EditTool.", FALSE];
IF key = $CharProps THEN {
MessageWindow.Append[" Set character properties with \"For selected characters\" option.", FALSE];
};
MessageWindow.Blink[];
}
ELSE {TextEdit.PutProp[node, key, value, TEditInput.CurrentEvent[]]}
};
};
name ¬ GetNameArg[info.propNameArg ! BadArg => GOTO Bad];
valueRope ¬ GetRopeArg[info.propValueArg ! BadArg => GOTO Bad];
key ¬ Atom.MakeAtom[name];
TEditSelection.LockSel[primary, "SetPropCom"];
pSel ¬ TEditOps.GetSelData[];
IF NOT EditToolPrivate.CheckPSel[pSel] OR NOT TEditInputOps.CheckReadonly[pSel] THEN {
TEditSelection.UnlockSel[primary];
RETURN;
};
root ¬ TEditSelection.SelectionRoot[pSel];
[] ¬ TEditLocks.Lock[root, "SetPropCom"];
ForEachNode[info.propNode, pSel, Put !
RuntimeError.UNCAUGHT => {
MessageWindow.Append["Uncaught error in EditToolMiscImpl.SetPropCom", TRUE];
MessageWindow.Blink[];
CONTINUE;
};
];
TEditSelection.UnlockDocAndPSel[root];
EXITS Bad => RETURN
};
RemoveProp
removePropAtom: LIST OF REF =
EditToolPrivate.Register[$RemoveNodeProp, RemovePropOp];
RemovePropButton: Buttons.ButtonProc = {
EditToolPrivate.DoButton[removePropAtom]
};
RemovePropOp: TEditInput.CommandProc = {
RemovePropCom[EditToolPrivate.mainToolInfo];
};
RemovePropCom: PROC [info: EditToolPrivate.Info] = {
pSel: TEditDocument.Selection;
root: TextNode.Ref;
key: ATOM;
Rem: PROC [node: TextNode.Ref, start, size: INT] = {
IF info.propNode = forSelectedChars THEN
TextEdit.PutCharProp[node: node, index: start, name: key, value: NIL, nChars: size, event: TEditInput.CurrentEvent[], root: root]
ELSE
TextEdit.PutProp[node, key, NIL, TEditInput.CurrentEvent[]]
};
key ¬ Atom.MakeAtom[GetNameArg[info.propNameArg ! BadArg => GOTO Bad]];
TEditSelection.LockSel[primary, "RemovePropCom"];
pSel ¬ TEditOps.GetSelData[];
IF NOT EditToolPrivate.CheckPSel[pSel] OR NOT TEditInputOps.CheckReadonly[pSel] THEN {
TEditSelection.UnlockSel[primary];
RETURN;
};
root ¬ TEditSelection.SelectionRoot[pSel];
[] ¬ TEditLocks.Lock[root, "RemovePropCom"];
ForEachNode[info.propNode, pSel, Rem];
TEditSelection.UnlockDocAndPSel[root];
EXITS Bad => RETURN
};
ListProps
listPropsAtom: LIST OF REF =
EditToolPrivate.Register[$ListNodeProps, ListPropsOp];
ListPropsButton: Buttons.ButtonProc = {
EditToolPrivate.DoButton[listPropsAtom]
};
ListPropsOp: TEditInput.CommandProc = {
ListPropsCom[EditToolPrivate.mainToolInfo];
};
ListPropsCom: PROC [info: EditToolPrivate.Info] = {
pSel: TEditDocument.Selection;
valueRope: ROPE;
root: TextNode.Ref;
list: LIST OF ATOM ¬ NIL;
listProp: PROC [name: ATOM, value: REF] RETURNS[BOOLEAN] = {
IF value#NIL THEN {list ¬ CONS[name, list]};
RETURN [FALSE];
};
List: PROC[node: TextNode.Ref, start, size: INT] = {
IF info.propNode = forSelectedChars THEN {
IF node.charProps#NIL THEN FOR i: INT IN [start..start+size) DO
FOR p: TextEdit.PropList ¬ TextEdit.GetCharPropList[node, i], p.rest UNTIL p=NIL DO
[] ¬ listProp[NARROW[p.first.key], p.first.val];
ENDLOOP;
ENDLOOP;
}
ELSE [] ¬ NodeProps.MapProps[node, listProp];
};
TEditSelection.LockSel[primary, "ListPropsCom"];
pSel ¬ TEditOps.GetSelData[];
IF NOT EditToolPrivate.CheckPSel[pSel] THEN {
TEditSelection.UnlockSel[primary];
RETURN;
};
root ¬ TEditSelection.SelectionRoot[pSel];
[] ¬ TEditLocks.Lock[root, "ListPropsCom", read];
ForEachNode[info.propNode, pSel, List];
TEditSelection.UnlockDocAndPSel[root];
FOR lst: LIST OF ATOM ¬ list, lst.rest UNTIL lst=NIL DO
valueRope ¬ Rope.Concat[valueRope, Atom.GetPName[lst.first]];
IF lst.rest # NIL THEN valueRope ¬ Rope.Concat[valueRope, " "];
ENDLOOP;
TEditOps.SetTextContents[info.propNameArg, valueRope]
};
FindProp
findPropAtom: LIST OF REF =
EditToolPrivate.Register[$FindNodeProp, FindPropOp];
findBackPropAtom: LIST OF REF =
EditToolPrivate.Register[$BackFindNodeProp, FindBackPropOp];
FindPropButton: Buttons.ButtonProc = {
EditToolPrivate.DoButton[findPropAtom, findBackPropAtom, mouseButton=red]
};
FindPropOp: TEditInput.CommandProc = {
FindPropCom[EditToolPrivate.mainToolInfo, TRUE];
};
FindBackPropOp: TEditInput.CommandProc = {
FindPropCom[EditToolPrivate.mainToolInfo, FALSE];
};
FindPropCom: PROC [info: EditToolPrivate.Info, forward: BOOLEAN] = {
pSel: TEditDocument.Selection;
root: TextNode.Ref ¬ NIL;
node: TextNode.Ref;
{
startNode: TextNode.Ref;
startCharFound: INT ¬ 0;
endCharFound: INT ¬ 0;
pattern: ROPE;
tester: TextNode.RefTextNode ¬ TextNode.NewTextNode[];
name: ATOM; -- property name we're looking for
finder: TreeFind.Finder; -- pattern for property value
Step: PROC [n: TextNode.Ref] RETURNS [TextNode.Ref] = {
RETURN [IF forward THEN TextNode.StepForward[n] ELSE TextNode.StepBackward[n]]
};
name ¬ Atom.MakeAtom[GetNameArg[info.propNameArg ! BadArg => GOTO Bad]];
pattern ¬ TextEdit.GetRope[EditToolBuilder.GetDataNode[info.propPatternArg]];
IF Rope.Size[pattern] # 0 THEN -- create a finder for the pattern
finder ¬ TreeFind.CreateFromRope[pattern !
TextFind.MalformedPattern => { ReportPatternError[ec]; GOTO Bad }];
TEditSelection.LockSel[primary, "FindPropCom"];
pSel ¬ TEditOps.GetSelData[];
IF NOT EditToolPrivate.CheckPSel[pSel] THEN {
MessageWindow.Append["Select node.", TRUE];
MessageWindow.Blink[];
TEditSelection.UnlockSel[primary];
RETURN;
};
root ¬ TEditSelection.SelectionRoot[pSel];
[] ¬ TEditLocks.Lock[root, "FindPropCom", read];
node ¬ NIL; -- start for search
startNode ¬ IF forward THEN pSel.end.pos.node ELSE pSel.start.pos.node;
IF finder#NIL
THEN FOR n: TextNode.Ref ¬ startNode, Step[n] UNTIL n = NIL DO
IF info.propNode = forSelectedChars THEN {
selectionPoint: TEditDocument.SelectionPoint ~ IF forward THEN pSel.end ELSE pSel.start;
SearchCharProps: PROC RETURNS [found: BOOLEAN ¬ FALSE] ~ {
prev: REF ¬ NIL;
foundRope: ROPE ¬ NIL;
CharAction: PROC [i: INT] ~ {
value: REF ¬ TextEdit.GetCharProp[n, i, name];
IF value # prev AND value # NIL THEN {
tester.rope ¬ NodeProps.GetSpecs[name, value];
IF TextFind.Try[finder, tester].found THEN {
startCharFound ¬ i;
endCharFound ¬ i+1;
foundRope ¬ tester.rope;
prev ¬ value;
found ¬ TRUE;
};
prev ¬ value;
};
};
CheckChar: PROC [i: INT] RETURNS [stop: BOOLEAN] ~ {
value: REF ¬ TextEdit.GetCharProp[n, i, name];
IF value # prev OR NOT Rope.Equal[foundRope, NodeProps.GetSpecs[name, value]] THEN RETURN [TRUE];
startCharFound ¬ MIN[startCharFound, i];
endCharFound ¬ MAX[endCharFound, i+1];
prev ¬ value;
RETURN [FALSE];
};
IF forward THEN {
FOR i: INT IN [startChar..endChar) UNTIL found DO CharAction[i] ENDLOOP;
IF found THEN FOR i: INT IN [endCharFound..endChar) UNTIL CheckChar[i].stop DO ENDLOOP;
}
ELSE {
FOR i: INT DECREASING IN [startChar..endChar) UNTIL found DO CharAction[i] ENDLOOP;
IF found THEN FOR i: INT DECREASING IN [startChar..startCharFound) UNTIL CheckChar[i].stop DO ENDLOOP;
}
};
startChar: INT ¬ 0;
endChar: INT ¬ TextEdit.Size[n];
IF n = startNode AND selectionPoint.pos.where = TextNode.NodeItself THEN LOOP
ELSE IF n = startNode THEN {
IF forward THEN startChar ¬ MAX[MIN[selectionPoint.pos.where+1, endChar], startChar]
ELSE endChar ¬ MIN[MAX[selectionPoint.pos.where, startChar], endChar]
};
IF n.hascharprops AND SearchCharProps[].found THEN {node ¬ n; EXIT};
}
ELSE IF n # startNode THEN {
value: REF ¬ NodeProps.GetProp[n, name];
IF value # NIL THEN { -- see if matches pattern
tester.rope ¬ NodeProps.GetSpecs[name, value];
IF TextFind.Try[finder, tester].found THEN {node ¬ n; EXIT};
};
};
ENDLOOP;
IF node=NIL OR TextNode.Parent[node]=NIL THEN {
MessageWindow.Append["Failed to find property matching given pattern.", TRUE];
MessageWindow.Blink[];
TEditSelection.UnlockDocAndPSel[root];
RETURN;
};
IF info.propNode = forSelectedChars THEN {
EditToolPrivate.tSel.start.pos ¬ [node, startCharFound];
EditToolPrivate.tSel.end.pos ¬ [node, endCharFound-1];
EditToolPrivate.tSel.granularity ¬ char;
}
ELSE {
EditToolPrivate.tSel.start.pos ¬ [node, 0];
EditToolPrivate.tSel.end.pos ¬ [node, MAX[TextEdit.Size[node], 1]-1];
EditToolPrivate.tSel.granularity ¬ node;
};
EditToolPrivate.tSel.viewer ¬ pSel.viewer;
EditToolPrivate.tSel.data ¬ pSel.data;
EditToolPrivate.tSel.insertion ¬ after;
TEditSelection.MakeSelection[new: EditToolPrivate.tSel];
TEditInput.CloseEvent[];
TEditRefresh.ScrollToEndOfSel[EditToolPrivate.tSel.viewer, FALSE];
TEditSelection.UnlockDocAndPSel[root];
GetPropCom[info];
EXITS Bad => { RETURN; }
}
};
ReportPatternError: PUBLIC PROC [ec: TextFind.PatternErrorCode] = {
msg: ROPE = SELECT ec FROM
toobig => "Pattern too long",
endquote => "Pattern ends with quote (')",
endtilda => "Pattern ends with tilde (~)",
boundary => "Pattern has | inside rather than at beginning or end",
missingNameEnd => "Pattern has < without matching >",
unmatchedNameEnd => "Pattern has > without previous <",
ENDCASE => "Pattern error (consult CedarSupport^)";
MessageWindow.Append[msg, TRUE];
MessageWindow.Blink[]
};
END.