EditToolMiscImpl.mesa
Copyright (C) 1982, 1983, 1984, 1985 by Xerox Corporation. All rights reserved.
Paxton on November 24, 1982 8:45 am
McGregor on August 30, 1982 2:24 pm
Maxwell, January 6, 1983 12:17 pm
Russ Atkinson, July 26, 1983 4:49 pm
Doug Wyatt, January 9, 1985 4:22:22 pm PST
DIRECTORY
Atom USING [GetPName, MakeAtom],
Buttons USING [ButtonProc],
EditToolBuilder USING [BuildButton, BuildDataFieldPair, BuildPair, DataFieldButton, GetDataNode, HGap, ToMiddle, ToNext, VGap],
EditToolPrivate USING [ChangeState, CheckPSel, DoButton, Info, mainToolInfo, NodeKind, Register, root, selection, tSel],
Labels USING [Set],
MessageWindow USING [Append, Blink],
NameSymbolTable USING [Name, nullName, RopeFromName],
NodeProps USING [DoSpecs, GetProp, GetSpecs, MapProps],
NodeStyle USING [StyleNameForNode],
Process USING [Detach],
Rope USING [Concat, Equal, Fetch, ROPE, Size, Substr],
RopeEdit USING [AlphaNumericChar, BlankChar],
TEditDocument USING [Selection],
TEditInput USING [CloseEvent, CommandProc, CurrentEvent],
TEditInputOps USING [CheckReadonly, LoadAbbreviations, ReloadStyleName, SetStyleName, SetTypeName],
TEditLocks USING [Lock],
TEditOps USING [GetSelData, SetTextContents],
TEditRefresh USING [ScrollToEndOfSel],
TEditSelection USING [LockSel, MakeSelection, pSel, SelectionRoot, UnlockDocAndPSel, UnlockSel],
TextEdit USING [GetProp, GetRope, PutProp, Size],
TextFind USING [CreateFromRope, Finder, MalformedPattern, PatternErrorCode, Try],
TextNode USING [NarrowToTextNode, NewTextNode, Parent, Ref, RefTextNode, Root, StepBackward, StepForward],
TreeFind USING [CreateFromRope, Finder],
ViewerClasses USING [Viewer],
ViewerOps USING [EnumerateChildren, EnumerateViewers, PaintViewer];
EditToolMiscImpl: CEDAR PROGRAM
IMPORTS EditToolPrivate, EditToolBuilder, Atom, TEditOps, Labels, MessageWindow, NameSymbolTable, NodeProps, NodeStyle, Process, Rope, RopeEdit, TextEdit, TextFind, TextNode, TEditSelection, TEditRefresh, TEditInput, TEditInputOps, TEditLocks, TreeFind, ViewerOps
EXPORTS EditToolPrivate
= { OPEN EditToolPrivate, EditToolBuilder;
----------------------------
BuildPropertyButtons: PUBLIC PROC [info: Info] = { OPEN info;
[,propNameArg] ← BuildDataFieldPair[layout, "Property name:", PropNameArgButton, info, 1];
VGap[layout];
[,propValueArg] ← BuildDataFieldPair[layout, "Property value:", PropValueArgButton, info, 1];
VGap[layout];
propNode ← selection;
[] ← BuildButton[layout, "Get", GetPropButton, info];
[] ← BuildButton[layout, "Set", SetPropButton, info];
[] ← BuildButton[layout, "Remove", RemovePropButton, info];
[] ← BuildButton[layout, "List", ListPropsButton, info];
ToMiddle[layout];
[propNodeLabel,] ←
BuildPair[layout,PropNodeButton,propNode,selectionNameRope,rootNameRope,info];
ToNext[layout];
[] ← BuildButton[layout, "Find", FindPropButton, info];
HGap[layout];
[,propPatternArg] ← BuildDataFieldPair[layout, "Value pattern:", PropPatternArgButton, info, 1];
};
----------------------------
BuildStyleButtons: PUBLIC PROC [info: Info] = { OPEN info;
[,styleNameArg] ← BuildDataFieldPair[layout, "Style name:", StyleNameArgButton, info, 1];
VGap[layout];
styleNode ← root;
[] ← BuildButton[layout, "Get", GetStyleNameButton, info];
[] ← BuildButton[layout, "Set", SetStyleNameButton, info];
[] ← BuildButton[layout, "Clear", ClearStyleNameButton, info];
ToMiddle[layout];
[styleNodeLabel,] ← BuildPair[layout,StyleNameNodeButton,styleNode,
selectionNameRope,rootNameRope,info];
ToNext[layout];
[] ← BuildButton[layout, "LoadStyleDefinition", LoadStyleButton, info];
[] ← BuildButton[layout, "LoadAbbreviations", LoadAbbreviationsButton, info];
};
----------------------------
BuildTypeButtons: PUBLIC PROC [info: Info] = { OPEN info;
[,typeNameArg] ← BuildDataFieldPair[layout, "Format name:", TypeNameArgButton, info, 1];
VGap[layout];
typeNode ← selection;
[] ← BuildButton[layout, "Get", GetTypeNameButton, info];
[] ← BuildButton[layout, "Set", SetTypeNameButton, info];
[] ← BuildButton[layout, "Clear", ClearTypeNameButton, info];
ToMiddle[layout];
[typeNodeLabel,] ← BuildPair[layout,TypeNameNodeButton,
typeNode,selectionNameRope,rootNameRope,info];
};
----------------------------
BadName: ERROR = CODE;
GetNameArg: PROC [arg: ViewerClasses.Viewer] RETURNS [name: Rope.ROPE] = {
Bad: PROC = { OPEN MessageWindow;
Append["Enter name consisting of one or more alphanumeric characters.", TRUE];
Blink[];
ERROR BadName };
start, end, size: INT ← 0;
rope: Rope.ROPE ← TextEdit.GetRope[GetDataNode[arg]];
end ← size ← Rope.Size[rope];
FOR i:INT IN [0..size) DO -- skip to first nonblank
IF ~RopeEdit.BlankChar[Rope.Fetch[rope,i]] THEN { start ← i; EXIT };
ENDLOOP;
FOR i:INT IN (start..size) DO -- count the AlphaNumericChar's
IF ~RopeEdit.AlphaNumericChar[Rope.Fetch[rope,i]] THEN { end ← i; EXIT };
ENDLOOP;
IF end=start THEN Bad[];
name ← Rope.Substr[rope,start,end-start];
FOR i:INT IN (end..size) DO -- check that rest is blanks
IF ~RopeEdit.BlankChar[Rope.Fetch[rope,i]] THEN Bad[];
ENDLOOP;
};
ForEachNode: PROC [
nodeKind: NodeKind, pSel: TEditDocument.Selection, proc: PROC [TextNode.Ref]] = {
SELECT nodeKind FROM
root => proc[TextNode.Root[pSel.start.pos.node]];
selection =>
FOR node: TextNode.Ref ← pSel.start.pos.node, TextNode.StepForward[node] DO
proc[node];
IF node = pSel.end.pos.node THEN EXIT;
ENDLOOP;
ENDCASE => ERROR };
SetNodeName: PROC [
info: Info, name: Rope.ROPE, style: BOOLEAN, pSel: TEditDocument.Selection] = {
Set: PROC [node: TextNode.Ref] = {
IF style THEN TEditInputOps.SetStyleName[name, node]
ELSE TEditInputOps.SetTypeName[name, node] };
ForEachNode[IF style THEN info.styleNode ELSE info.typeNode, pSel, Set] };
----------------------------
styleNameArgAtom: LIST OF REF = Register[$StyleName,StyleNameArgOp];
clearStyleNameArgAtom: LIST OF REF = Register[$ClearStyleName,ClearStyleNameArgOp];
StyleNameArgButton: Buttons.ButtonProc = {
DoButton[styleNameArgAtom, clearStyleNameArgAtom, mouseButton=red] };
StyleNameArgOp: TEditInput.CommandProc = {
DataFieldButton[mainToolInfo.styleNameArg,FALSE] };
ClearStyleNameArgOp: TEditInput.CommandProc = {
DataFieldButton[mainToolInfo.styleNameArg,TRUE] };
----------------------------
typeNameArgAtom: LIST OF REF = Register[$TypeName,TypeNameArgOp];
clearTypeNameArgAtom: LIST OF REF = Register[$ClearTypeName,ClearTypeNameArgOp];
TypeNameArgButton: Buttons.ButtonProc = {
DoButton[typeNameArgAtom,clearTypeNameArgAtom, mouseButton=red] };
TypeNameArgOp: TEditInput.CommandProc = {
DataFieldButton[mainToolInfo.typeNameArg,FALSE] };
ClearTypeNameArgOp: TEditInput.CommandProc = {
DataFieldButton[mainToolInfo.typeNameArg,TRUE] };
----------------------------
getStyleNameAtom: LIST OF REF = Register[$GetNodeStyleName,GetStyleNameOp];
GetStyleNameButton: Buttons.ButtonProc = {
DoButton[getStyleNameAtom] };
GetStyleNameOp: TEditInput.CommandProc = { GetStyleNameCom[mainToolInfo] };
GetStyleNameCom: PROC [info: Info] = { GetNameCom[info,TRUE] };
getTypeNameAtom: LIST OF REF = Register[$GetNodeTypeName,GetTypeNameOp];
GetTypeNameButton: Buttons.ButtonProc = {
DoButton[getTypeNameAtom] };
GetTypeNameOp: TEditInput.CommandProc = { GetTypeNameCom[mainToolInfo] };
GetTypeNameCom: PROC [info: Info] = { GetNameCom[info,FALSE] };
NotUniform: SIGNAL = CODE;
GetNameCom: PROC [info: Info, style: BOOLEAN] = { OPEN info;
pSel: TEditDocument.Selection = TEditOps.GetSelData[];
nodeKind: NodeKind ← IF style THEN info.styleNode ELSE info.typeNode;
name: NameSymbolTable.Name ← NameSymbolTable.nullName;
arg: ViewerClasses.Viewer ← IF style THEN info.styleNameArg ELSE info.typeNameArg;
Get: PROC [node: TextNode.Ref] = {
n: NameSymbolTable.Name ← IF style THEN NodeStyle.StyleNameForNode[node]
ELSE node.typename;
IF name = NameSymbolTable.nullName THEN name ← n
ELSE IF name # n THEN { OPEN MessageWindow;
Append[IF style THEN "Nodes don't have uniform style. Using first."
ELSE "Nodes don't have uniform format. Using first.", TRUE];
Blink[];
SIGNAL NotUniform }};
IF ~CheckPSel[pSel] THEN RETURN;
ForEachNode[nodeKind, pSel, Get ! NotUniform => CONTINUE];
TEditOps.SetTextContents[arg, NameSymbolTable.RopeFromName[name]];
};
----------------------------
setStyleNameAtom: LIST OF REF = Register[$SetNodeStyleName,SetStyleNameOp];
SetStyleNameButton: Buttons.ButtonProc = {
DoButton[setStyleNameAtom] };
SetStyleNameOp: TEditInput.CommandProc = { SetStyleNameCom[mainToolInfo] };
SetStyleNameCom: PROC [info: Info] = { SetNameCom[info,TRUE] };
setTypeNameAtom: LIST OF REF = Register[$SetNodeTypeName,SetTypeNameOp];
SetTypeNameButton: Buttons.ButtonProc = {
DoButton[setTypeNameAtom] };
SetTypeNameOp: TEditInput.CommandProc = { SetTypeNameCom[mainToolInfo] };
SetTypeNameCom: PROC [info: Info] = { SetNameCom[info,FALSE] };
SetNameCom: PROC [info: Info, style: BOOLEAN] = {
pSel: TEditDocument.Selection;
arg: ViewerClasses.Viewer ← IF style THEN info.styleNameArg ELSE info.typeNameArg;
name: Rope.ROPE ← GetNameArg[arg ! BadName => GOTO Bad];
TEditSelection.LockSel[primary, "SetNameCom"];
pSel ← TEditOps.GetSelData[];
IF ~CheckPSel[pSel] OR ~TEditInputOps.CheckReadonly[pSel] THEN {
TEditSelection.UnlockSel[primary]; RETURN };
SetNodeName[info,name,style,pSel];
TEditSelection.UnlockSel[primary];
EXITS Bad => RETURN };
----------------------------
clearTypeNameAtom: LIST OF REF = Register[$ClearNodeTypeName,ClearTypeNameOp];
ClearTypeNameButton: Buttons.ButtonProc = {
DoButton[clearTypeNameAtom] };
ClearTypeNameOp: TEditInput.CommandProc = { ClearTypeNameCom[mainToolInfo] };
ClearTypeNameCom: PROC [info: Info] = {
pSel: TEditDocument.Selection = TEditOps.GetSelData[];
IF ~CheckPSel[pSel] THEN RETURN;
IF ~TEditInputOps.CheckReadonly[pSel] THEN RETURN;
SetNodeName[info,NIL,FALSE,pSel] };
clearStyleNameAtom: LIST OF REF = Register[$ClearNodeStyleName,ClearStyleNameOp];
ClearStyleNameButton: Buttons.ButtonProc = {
DoButton[clearStyleNameAtom] };
ClearStyleNameOp: TEditInput.CommandProc = { ClearStyleNameCom[mainToolInfo] };
ClearStyleNameCom: PROC [info: Info] = {
pSel: TEditDocument.Selection = TEditOps.GetSelData[];
IF ~CheckPSel[pSel] THEN RETURN;
IF ~TEditInputOps.CheckReadonly[pSel] THEN RETURN;
SetNodeName[info,NIL,TRUE,pSel] };
----------------------------
loadStyleAtom: LIST OF REF = Register[$LoadStyleDefinition,LoadStyleOp];
LoadStyleButton: Buttons.ButtonProc = {
DoButton[loadStyleAtom] };
LoadStyleOp: TEditInput.CommandProc = { LoadStyle[mainToolInfo] };
LoadStyle: PROC [info: Info] = {
repaint: PROC [v: ViewerClasses.Viewer] RETURNS [BOOLTRUE] = {
SELECT v.class.flavor FROM
$Text => TRUSTED {Process.Detach[FORK ViewerOps.PaintViewer[v, all]]};
$Container => ViewerOps.EnumerateChildren[v, repaint];
ENDCASE;
RETURN [TRUE] };
name: Rope.ROPE ← GetNameArg[info.styleNameArg ! BadName => GOTO Bad];
TEditInputOps.ReloadStyleName[name];
ViewerOps.EnumerateViewers[repaint];
EXITS Bad => RETURN };
----------------------------
loadAbbreviationsAtom: LIST OF REF = Register[$LoadAbbreviations,LoadAbbreviationsOp];
LoadAbbreviationsButton: Buttons.ButtonProc = {
DoButton[loadAbbreviationsAtom] };
LoadAbbreviationsOp: TEditInput.CommandProc = { LoadAbbreviations[mainToolInfo] };
LoadAbbreviations: PROC [info: Info] = {
name: Rope.ROPE ← GetNameArg[info.styleNameArg ! BadName => GOTO Bad];
TEditInputOps.LoadAbbreviations[name];
EXITS Bad => RETURN };
----------------------------
rootNameRope: Rope.ROPE = "For root node";
selectionNameRope: Rope.ROPE = "For selected nodes";
rootTypeNameAtom: LIST OF REF = Register[$TypeNameForRoot,RootTypeNameOp];
selTypeNameAtom: LIST OF REF = Register[$TypeNameForSelection,SelectionTypeNameOp];
TypeNameNodeButton: Buttons.ButtonProc = {
ChangeState[mainToolInfo.typeNode, selTypeNameAtom, rootTypeNameAtom] };
RootTypeNameOp: TEditInput.CommandProc = { RootTypeName[mainToolInfo] };
RootTypeName: PROC [info: Info] = { OPEN info;
typeNode ← root;
Labels.Set[typeNodeLabel,rootNameRope] };
SelectionTypeNameOp: TEditInput.CommandProc = { SelectionTypeName[mainToolInfo] };
SelectionTypeName: PROC [info: Info] = { OPEN info;
typeNode ← selection;
Labels.Set[typeNodeLabel,selectionNameRope] };
rootStyleNameAtom: LIST OF REF = Register[$StyleNameForRoot,RootStyleNameOp];
selStyleNameAtom: LIST OF REF = Register[$StyleNameForSelection,SelectionStyleNameOp];
StyleNameNodeButton: Buttons.ButtonProc = {
ChangeState[mainToolInfo.styleNode, selStyleNameAtom, rootStyleNameAtom] };
RootStyleNameOp: TEditInput.CommandProc = { RootStyleName[mainToolInfo] };
RootStyleName: PROC [info: Info] = { OPEN info;
styleNode ← root;
Labels.Set[styleNodeLabel,rootNameRope] };
SelectionStyleNameOp: TEditInput.CommandProc = { SelectionStyleName[mainToolInfo] };
SelectionStyleName: PROC [info: Info] = { OPEN info;
styleNode ← selection;
Labels.Set[styleNodeLabel,selectionNameRope] };
----------------------------
propNameArgAtom: LIST OF REF = Register[$PropName,PropNameArgOp];
clearPropNameArgAtom: LIST OF REF = Register[$ClearPropName,ClearPropNameArgOp];
PropNameArgButton: Buttons.ButtonProc = {
DoButton[propNameArgAtom,clearPropNameArgAtom, mouseButton=red] };
PropNameArgOp: TEditInput.CommandProc = { PropNameArg[mainToolInfo] };
PropNameArg: PROC [info: Info] = { DataFieldButton[info.propNameArg,FALSE] };
ClearPropNameArgOp: TEditInput.CommandProc = { ClearPropNameArg[mainToolInfo] };
ClearPropNameArg: PROC [info: Info] = { DataFieldButton[info.propNameArg,TRUE] };
----------------------------
propValueArgAtom: LIST OF REF = Register[$PropValue,PropValueArgOp];
clearPropValueArgAtom: LIST OF REF = Register[$ClearPropValue,ClearPropValueArgOp];
PropValueArgButton: Buttons.ButtonProc = {
DoButton[propValueArgAtom,clearPropValueArgAtom, mouseButton=red] };
PropValueArgOp: TEditInput.CommandProc = { PropValueArg[mainToolInfo] };
PropValueArg: PROC [info: Info] = { DataFieldButton[info.propValueArg,FALSE] };
ClearPropValueArgOp: TEditInput.CommandProc = { ClearPropValueArg[mainToolInfo] };
ClearPropValueArg: PROC [info: Info] = { DataFieldButton[info.propValueArg,TRUE] };
----------------------------
propPatternArgAtom: LIST OF REF = Register[$PropPattern,PropPatternArgOp];
clearPropPatternArgAtom: LIST OF REF = Register[$ClearPropPattern,ClearPropPatternArgOp];
PropPatternArgButton: Buttons.ButtonProc = {
DoButton[propPatternArgAtom,clearPropPatternArgAtom, mouseButton=red] };
PropPatternArgOp: TEditInput.CommandProc = { PropPatternArg[mainToolInfo] };
PropPatternArg: PROC [info: Info] = { DataFieldButton[info.propPatternArg,FALSE] };
ClearPropPatternArgOp: TEditInput.CommandProc = { ClearPropPatternArg[mainToolInfo] };
ClearPropPatternArg: PROC [info: Info] = { DataFieldButton[info.propPatternArg,TRUE] };
----------------------------
rootPropAtom: LIST OF REF = Register[$PropForRoot,RootPropOp];
selPropAtom: LIST OF REF = Register[$PropForSelection,SelectionPropOp];
PropNodeButton: Buttons.ButtonProc = {
ChangeState[mainToolInfo.propNode, selPropAtom, rootPropAtom] };
RootPropOp: TEditInput.CommandProc = { RootProp[mainToolInfo] };
RootProp: PROC [info: Info] = { OPEN info;
propNode ← root;
Labels.Set[propNodeLabel,rootNameRope] };
SelectionPropOp: TEditInput.CommandProc = { SelectionProp[mainToolInfo] };
SelectionProp: PROC [info: Info] = { OPEN info;
propNode ← selection;
Labels.Set[propNodeLabel,selectionNameRope] };
----------------------------
getPropAtom: LIST OF REF = Register[$GetNodeProp,GetPropOp];
GetPropButton: Buttons.ButtonProc = {
DoButton[getPropAtom] };
GetPropOp: TEditInput.CommandProc = { GetPropCom[mainToolInfo] };
GetPropCom: PROC [info: Info] = { OPEN info;
pSel: TEditDocument.Selection;
root: TextNode.Ref;
name: Rope.ROPE;
key: ATOM;
valueRope: Rope.ROPE;
Get: PROC [node: TextNode.Ref] = {
vrope: Rope.ROPE ← NodeProps.GetSpecs[key,TextEdit.GetProp[node,name]];
IF valueRope = NIL THEN valueRope ← vrope
ELSE IF ~Rope.Equal[valueRope,vrope] THEN { OPEN MessageWindow;
Append["Nodes don't have uniform property values. Using first.", TRUE];
Blink[];
SIGNAL NotUniform }};
name ← GetNameArg[info.propNameArg ! BadName => GOTO Bad];
TEditSelection.LockSel[primary, "GetPropCom"];
pSel ← TEditOps.GetSelData[];
IF ~CheckPSel[pSel] THEN { TEditSelection.UnlockSel[primary]; RETURN };
root ← TEditSelection.SelectionRoot[pSel];
[] ← TEditLocks.Lock[root, "GetPropCom", read];
key ← Atom.MakeAtom[name];
ForEachNode[info.propNode, pSel, Get ! NotUniform => CONTINUE];
TEditSelection.UnlockDocAndPSel[root];
TEditOps.SetTextContents[propValueArg, valueRope];
EXITS Bad => RETURN };
----------------------------
setPropAtom: LIST OF REF = Register[$SetNodeProp,SetPropOp];
SetPropButton: Buttons.ButtonProc = {
DoButton[setPropAtom] };
SetPropOp: TEditInput.CommandProc = { SetPropCom[mainToolInfo] };
SetPropCom: PROC [info: Info] = { OPEN info;
pSel: TEditDocument.Selection;
name: Rope.ROPE;
key: ATOM;
root: TextNode.Ref;
valueRope: Rope.ROPE ← TextEdit.GetRope[GetDataNode[info.propValueArg]];
Put: PROC [node: TextNode.Ref] = {
TextEdit.PutProp[node, name,
NodeProps.DoSpecs[key,valueRope],
TEditInput.CurrentEvent[], root] };
name ← GetNameArg[info.propNameArg ! BadName => GOTO Bad];
TEditSelection.LockSel[primary, "SetPropCom"];
pSel ← TEditOps.GetSelData[];
IF ~CheckPSel[pSel] OR ~TEditInputOps.CheckReadonly[pSel] THEN {
TEditSelection.UnlockSel[primary]; RETURN };
key ← Atom.MakeAtom[name];
root ← TEditSelection.SelectionRoot[pSel];
[] ← TEditLocks.Lock[root, "SetPropCom"];
ForEachNode[info.propNode, pSel, Put];
TEditSelection.UnlockDocAndPSel[root];
EXITS Bad => RETURN };
----------------------------
removePropAtom: LIST OF REF = Register[$RemoveNodeProp,RemovePropOp];
RemovePropButton: Buttons.ButtonProc = {
DoButton[removePropAtom] };
RemovePropOp: TEditInput.CommandProc = { RemovePropCom[mainToolInfo] };
RemovePropCom: PROC [info: Info] = { OPEN info;
pSel: TEditDocument.Selection;
root: TextNode.Ref;
name: Rope.ROPE;
Rem: PROC [node: TextNode.Ref] = {
TextEdit.PutProp[node, name, NIL, TEditInput.CurrentEvent[]] };
name ← GetNameArg[info.propNameArg ! BadName => GOTO Bad];
TEditSelection.LockSel[primary, "RemovePropCom"];
pSel ← TEditOps.GetSelData[];
IF ~CheckPSel[pSel] OR ~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 };
----------------------------
listPropsAtom: LIST OF REF = Register[$ListNodeProps,ListPropsOp];
ListPropsButton: Buttons.ButtonProc = {
DoButton[listPropsAtom] };
ListPropsOp: TEditInput.CommandProc = { ListPropsCom[mainToolInfo] };
ListPropsCom: PROC [info: Info] = { OPEN info;
pSel: TEditDocument.Selection;
valueRope: Rope.ROPE;
root: TextNode.Ref;
list: LIST OF ATOMNIL;
listProp: PROC[name: ATOM, value: REF] RETURNS[BOOLEAN] = {
IF value=NIL THEN RETURN[FALSE]; -- since setting value to NIL is same as removing
FOR lst: LIST OF ATOM ← list, lst.rest UNTIL lst=NIL DO
IF lst.first = name THEN RETURN [FALSE];
ENDLOOP;
list ← CONS[name, list];
RETURN [FALSE];
};
List: PROC[node: TextNode.Ref] = { [] ← NodeProps.MapProps[node, listProp] };
TEditSelection.LockSel[primary, "ListPropsCom"];
pSel ← TEditOps.GetSelData[];
IF NOT 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[propNameArg, valueRope] };
----------------------------
findPropAtom: LIST OF REF = Register[$FindNodeProp,FindPropOp];
findBackPropAtom: LIST OF REF = Register[$BackFindNodeProp,FindBackPropOp];
FindPropButton: Buttons.ButtonProc = {
DoButton[findPropAtom,findBackPropAtom, mouseButton=red] };
FindPropOp: TEditInput.CommandProc = { FindPropCom[mainToolInfo,TRUE] };
FindBackPropOp: TEditInput.CommandProc = { FindPropCom[mainToolInfo,FALSE] };
FindPropCom: PROC [info: Info, forward: BOOLEAN] = { OPEN info;
pSel: TEditDocument.Selection;
root, node: TextNode.Ref; {
pattern: Rope.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] = INLINE {
RETURN [IF forward THEN TextNode.StepForward[n] ELSE TextNode.StepBackward[n]] };
name ← Atom.MakeAtom[GetNameArg[info.propNameArg ! BadName => GOTO Bad]];
pattern ← TextEdit.GetRope[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 ~CheckPSel[pSel] THEN {
OPEN MessageWindow; Append["Select node.", TRUE]; Blink[];
TEditSelection.UnlockSel[primary]; RETURN };
root ← TEditSelection.SelectionRoot[pSel];
[] ← TEditLocks.Lock[root, "FindPropCom", read];
node ← IF forward THEN pSel.end.pos.node ELSE pSel.start.pos.node; -- start for search
IF node # NIL THEN UNTIL (node ← Step[node])=NIL DO -- check for property
value: REF ← NodeProps.GetProp[node,name];
IF value # NIL THEN { -- see if matches pattern
IF finder=NIL THEN EXIT; -- accept anything
tester.rope ← NodeProps.GetSpecs[name,value];
IF TextFind.Try[finder,tester].found THEN EXIT };
ENDLOOP;
IF node=NIL OR TextNode.Parent[node]=NIL THEN {
OPEN MessageWindow;
Append["Failed to find node with property matching given pattern.", TRUE];
Blink[]; TEditSelection.UnlockDocAndPSel[root]; RETURN };
tSel.start.pos ← [node,0];
tSel.end.pos ← [node,MAX[TextEdit.Size[TextNode.NarrowToTextNode[node]],1]-1];
tSel.granularity ← node;
tSel.viewer ← pSel.viewer;
tSel.data ← pSel.data;
tSel.insertion ← after;
TEditSelection.MakeSelection[new: tSel];
TEditInput.CloseEvent[];
TEditRefresh.ScrollToEndOfSel[tSel.viewer, FALSE];
TEditSelection.UnlockDocAndPSel[root];
GetPropCom[info];
EXITS Bad => { TEditSelection.UnlockDocAndPSel[root]; RETURN }}};
ReportPatternError: PUBLIC PROC [ec: TextFind.PatternErrorCode] = {
msg: Rope.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[] };
----------------------------
}.
..