DIRECTORY Atom USING [GetPName, MakeAtom, PropList], Buttons USING [ButtonProc], EditToolBuilder USING [BuildButton, BuildDataFieldPair, BuildPair, BuildTriple, DataFieldButton, GetDataNode, HGap, ToMiddle, ToNext, VGap], EditToolPrivate USING [ChangeState, CheckPSel, CycleTriple, DoButton, Info, mainToolInfo, NodeKind, Register, tSel], Labels USING [Set], MessageWindow USING [Append, Blink], NodeProps USING [DoSpecs, GetProp, GetSpecs, MapProps], NodePropsExtras USING [Is], NodeStyleOps USING [StyleNameForNode], Process USING [Detach], Rope USING [Concat, Equal, Fetch, ROPE, Size, Substr], RopeEdit USING [AlphaNumericChar, BlankChar], RuntimeError USING [UNCAUGHT], TEditDocument USING [Selection, SelectionPoint], TEditInput USING [CloseEvent, CommandProc, CurrentEvent], TEditInputOps USING [CheckReadonly, LoadAbbreviations, ReloadStyleName, SetStyleName, SetFormatName], TEditLocks USING [Lock], TEditOps USING [GetSelData, SetTextContents], TEditRefresh USING [ScrollToEndOfSel], TEditSelection USING [LockSel, MakeSelection, pSel, SelectionRoot, UnlockDocAndPSel, UnlockSel], TextEdit USING [GetProp, GetRope, PutProp, Size, GetCharProp, PutCharProp, GetCharPropList], TextFind USING [Finder, MalformedPattern, PatternErrorCode, Try], TextNode USING [NodeItself, 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, NodeProps, NodePropsExtras, NodeStyleOps, Process, Rope, RopeEdit, RuntimeError, TextEdit, TextFind, TextNode, TEditSelection, TEditRefresh, TEditInput, TEditInputOps, TEditLocks, TreeFind, ViewerOps EXPORTS EditToolPrivate = BEGIN ROPE: TYPE ~ Rope.ROPE; 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]; [info.propNodeLabel, ] _ EditToolBuilder.BuildTriple[info.layout, PropNodeButton, ORD[info.propNode], rootNameRope, selectionNameRope, selectedCharsNameRope, 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: 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]; [info.styleNodeLabel, ] _ EditToolBuilder.BuildPair[info.layout, StyleNameNodeButton, info.styleNode=forSelectedNodes, selectionNameRope, rootNameRope, info]; EditToolBuilder.ToNext[info.layout]; [] _ EditToolBuilder.BuildButton[info.layout, "LoadStyleDefinition", LoadStyleButton, info]; [] _ EditToolBuilder.BuildButton[info.layout, "LoadAbbreviations", LoadAbbreviationsButton, info]; }; 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]; [info.formatNodeLabel, ] _ EditToolBuilder.BuildPair[info.layout, FormatNameNodeButton, info.formatNode=forSelectedNodes, selectionNameRope, rootNameRope, info]; }; BadName: ERROR = CODE; GetNameArg: PROC [arg: ViewerClasses.Viewer] RETURNS [name: ROPE] = { Bad: PROC = { MessageWindow.Append["Enter name consisting of one or more alphanumeric characters.", TRUE]; MessageWindow.Blink[]; ERROR BadName }; start, end, size: INT _ 0; rope: ROPE _ TextEdit.GetRope[EditToolBuilder.GetDataNode[arg]]; end _ size _ Rope.Size[rope]; FOR i:INT IN [0..size) DO -- skip to first nonblank IF NOT RopeEdit.BlankChar[Rope.Fetch[rope, i]] THEN { start _ i; EXIT }; ENDLOOP; FOR i:INT IN (start..size) DO -- count the AlphaNumericChar's IF NOT 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 NOT RopeEdit.BlankChar[Rope.Fetch[rope, i]] THEN Bad[]; ENDLOOP; }; 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] }; 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] }; 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] }; 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 node.formatName; 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]]; }; 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 ! BadName => 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 }; 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] }; 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 ! BadName => GOTO Bad]; TEditInputOps.ReloadStyleName[name]; ViewerOps.EnumerateViewers[repaint]; EXITS Bad => RETURN }; 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 ! BadName => GOTO Bad]; TEditInputOps.LoadAbbreviations[name]; EXITS Bad => RETURN }; rootNameRope: ROPE = "For root node"; selectionNameRope: ROPE = "For selected nodes"; selectedCharsNameRope: ROPE = "For selected characters"; 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, rootNameRope] }; SelectionFormatNameOp: TEditInput.CommandProc = { SelectionFormatName[EditToolPrivate.mainToolInfo]; }; SelectionFormatName: PROC [info: EditToolPrivate.Info] = { info.formatNode _ forSelectedNodes; Labels.Set[info.formatNodeLabel, selectionNameRope] }; 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, rootNameRope] }; SelectionStyleNameOp: TEditInput.CommandProc = { SelectionStyleName[EditToolPrivate.mainToolInfo]; }; SelectionStyleName: PROC [info: EditToolPrivate.Info] = { info.styleNode _ forSelectedNodes; Labels.Set[info.styleNodeLabel, selectionNameRope] }; 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]; }; 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] }; 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] }; 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, rootNameRope] }; SelectionPropOp: TEditInput.CommandProc = { SelectionProp[EditToolPrivate.mainToolInfo]; }; SelectionProp: PROC [info: EditToolPrivate.Info] = { info.propNode _ forSelectedNodes; Labels.Set[info.propNodeLabel, selectionNameRope] }; CharacterPropOp: TEditInput.CommandProc = { SelectedCharsProp[EditToolPrivate.mainToolInfo]; }; SelectedCharsProp: PROC [info: EditToolPrivate.Info] = { info.propNode _ forSelectedChars; Labels.Set[info.propNodeLabel, selectedCharsNameRope] }; 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.hascharprops 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 ! BadName => 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 }; 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: ROPE; key: ATOM; root: TextNode.Ref; valueRope: ROPE _ TextEdit.GetRope[EditToolBuilder.GetDataNode[info.propValueArg]]; 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 NodePropsExtras.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[], root]} }; }; name _ GetNameArg[info.propNameArg ! BadName => 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 }; 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[], root] }; key _ Atom.MakeAtom[GetNameArg[info.propNameArg ! BadName => 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 }; 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.hascharprops THEN FOR i: INT IN [start..start+size) DO FOR p: Atom.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] }; 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 ! BadName => 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. 6EditToolMiscImpl.mesa Copyright (C) 1982, 1983, 1984, 1985, 1986 by Xerox Corporation. All rights reserved. Doug Wyatt, January 9, 1985 4:22:22 pm PST 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 BuildPropertyButtons BuildStyleButtons BuildFormatButtons GetNameArg StyleNameArg FormatNameArg GetStyleName SetStyleName ClearFormat LoadStyle LoadAbbreviations Format/Style name ranges PropName PropValue PropPatternArg PropNode GetProp SetProp RemoveProp ListProps FindProp ΚŽ˜codešœ™KšœV™VKšœ*™*Kšœ)™)K™'K™0—K™šΟk ˜ Kšœœ!˜+Kšœœ˜Kšœœx˜Kšœœ`˜uKšœœ˜Kšœœ˜%Kšœ œ)˜8Kšœœ˜Kšœ œ˜'Kšœœ ˜Kšœœœ˜7Kšœ œ ˜.Kšœ œœ˜Kšœœ˜1Kšœ œ*˜:KšœœS˜fKšœ œ ˜Kšœ œ ˜.Kšœ œ˜'KšœœM˜aKšœ œO˜]Kšœ œ4˜BKšœ œW˜eKšœ œ˜)Kšœœ ˜Kšœ œ4˜C—headšœœ˜Kšœ‘˜˜Kšœ˜Kšœ˜K˜Kšœœœ˜K˜—šœ™šΟnœœœ$˜EK˜uK˜"K˜xK˜"Kšœ!˜!K˜JK˜JK˜PK˜MK˜&KšœRœO˜€K˜$K˜LK˜"K˜{K˜——šœ™šžœœœ$˜BK˜tK˜"Kšœ˜K˜OK˜OK˜SK˜&Kšœž˜žK˜$K˜\K˜bK˜——šœ™šžœœœ$˜CK˜wK˜"Kšœ#˜#K˜PK˜PK˜TK˜&Kšœ’˜’K˜——šœ ™ Kšœ œœ˜K˜šž œœœœ˜Ešžœœ˜KšœVœ˜\K˜Kšœ ˜K˜—Kšœœ˜Kšœœ6˜@K˜š œœœ œΟc˜3Kšœœ)œœ˜HKšœ˜—š œœœœŸ˜=Kšœœ0œ œ˜MKšœ˜—Kšœ œ˜K˜+š œœœ œŸ˜8Kšœœ)œ˜:Kšœ˜—K˜—K˜š ž œœKœœœ˜‘šœ ˜Kšœ:˜:šœ'˜'šœF˜KKšœœ˜Kšœœ˜šœœ,œ˜SKšœ˜Kšœ˜—šœœ*œ˜OKšœœ˜%Kšœ˜—Kšœ0˜0Kšœœœ˜&Kšœ˜—Kšœ˜—Kšœœ˜—K˜—K˜šž œœ$œ œ$˜mšžœœœœ˜9Kšœœ'˜4Kšœ)˜-K˜—Kšœ œœœ˜JK˜—K˜—šœ ™ Kšœœœœ8˜UKšœœœœB˜dK˜šžœ˜*K˜SK˜—K˜šžœ˜*KšœKœ˜RK˜K˜—šžœ˜/KšœKœ˜QK˜—K˜—šœ ™ Kšœœœœ:˜XKšœœœœ8˜TKšœœœœD˜gKšœœœœB˜cK˜šžœ˜+K˜UK˜—K˜šžœ˜+KšœLœ˜SK˜K˜—šžœ˜0KšœLœ˜RK˜—K˜—šœ ™ Kšœœœœ?˜\K˜šžœ˜*K˜+K˜—K˜šžœ˜*Kšœ.˜.Kšœ˜K˜—šžœœ!˜6Kšœœ˜Kšœ˜—K˜KšœœœœA˜_Kšœœœœ?˜[K˜šžœ˜+K˜,K˜—K˜šžœ˜+Kšœ/˜/Kšœ˜K˜—šžœœ!˜7Kšœœ˜Kšœ˜—K˜Kšœ œœ˜šž œœ%œ˜DK˜6Kšœ%œœœ˜WKšœœœ˜Kšœœœœ˜Tšžœœ#œ˜4šœœœœ$˜;Kšœ˜—šœœœ ˜šœœ œ˜Kš œœœ1œ3œ˜—K˜Kšœ ˜K˜—K˜—Kšœœ!œœ˜3Kšœ0œ˜:Kš œœœœœœ˜MK˜—K˜—šœ ™ Kšœœœœ?˜\K˜šžœ˜*K˜+K˜—K˜šžœ˜*Kšœ.˜.Kšœ˜K˜—šžœœ!˜6Kšœœ˜Kšœ˜—K˜KšœœœœA˜_Kšœœœœ?˜[K˜šžœ˜+K˜,K˜—K˜šžœ˜+Kšœ/˜/Kšœ˜K˜—šžœœ!˜7Kšœœ˜Kšœ˜K˜—šž œœ%œ˜AK˜Kšœœœœ˜TKšœœœ˜3K˜.K˜š œœ!œœ#œ˜VKšœ"˜"Kšœ˜K˜—K˜%K˜"Kšœœ˜K˜—K˜—šœ ™ KšœœœœE˜eKšœœœœC˜aK˜šžœ˜-K˜.K˜—K˜šžœ˜-Kšœ1˜1Kšœ˜K˜—šžœœ!˜9K˜6Kšœœ!œœ˜3Kšœœ#œœ˜5Kšœœœ˜$K˜—K˜KšœœœœC˜bK˜šžœ˜,K˜-K˜—K˜šžœ˜,Kšœ0˜0Kšœ˜K˜—šžœœ!˜8K˜6Kšœœ!œœ˜3Kšœœ#œœ˜5Kšœœœ˜#K˜—K˜—šœ ™ Kšœœœœ?˜YK˜šžœ˜'K˜(K˜—K˜šž œ˜'Kšœ(˜(Kšœ˜K˜—šž œœ"˜1š žœœœœœ˜Ašœ˜Kšœ œœ!˜FK˜6Kšœ˜—Kšœœ˜K˜—Kšœœ-œ˜AK˜$K˜$Kšœœ˜K˜—K˜—šœ™KšœœœœE˜gK˜šžœ˜/K˜0K˜—K˜šžœ˜/Kšœ0˜0Kšœ˜K˜—šžœœ"˜9Kšœœ-œ˜AK˜&Kšœœ˜K˜—K˜—šœ™Kšœœ˜%Kšœœ˜/Kšœœ˜8KšœœœœB˜aKšœœœœ@˜]KšœœœœL˜jKšœœœœJ˜fK˜šžœ˜,K˜}K˜—K˜šžœ˜,Kšœ-˜-Kšœ˜K˜—šžœœ$˜8Kšœ˜K˜/K˜—K˜šžœ˜1Kšœ2˜2Kšœ˜K˜—šžœœ$˜=Kšœ#˜#K˜4K˜—K˜Kšœœœœ@˜^KšœœœœJ˜gK˜šžœ˜+K˜zK˜—K˜šžœ˜+Kšœ,˜,Kšœ˜K˜—šž œœ$˜7Kšœ˜K˜.K˜—K˜šžœ˜0Kšœ1˜1Kšœ˜K˜—šžœœ$˜Kšœ0˜0Kšœ˜—Kšœ˜—Kšœ*˜.K˜—Kšœ0œ˜:K˜K˜.K˜šœœ!œ˜-Kšœ"˜"Kšœ˜Kšœ˜—K˜*K˜/Kšœ5œ˜?K˜&K˜7Kšœœ˜K˜—K˜—šœ™Kšœ œœœ5˜MK˜šž œ˜%K˜&K˜—K˜šž œ˜%Kšœ)˜)Kšœ˜K˜—šž œœ$˜4K˜Kšœœ˜ Kšœœ˜ K˜Kšœ œD˜Sšžœœ#œ˜4Kšœœ%˜/šœ"˜(K•StartOfExpansion’[node: TextEdit.RefTextNode, index: INT, name: ATOM, value: REF ANY, nChars: INT _ 1, event: TextEdit.Event _ NIL, root: TextEdit.RefTextNode _ NIL]šœƒ˜ƒ—šœ˜šœ&œ˜.šœ&œ˜,Kšœ)œ˜0Kšœ:œ˜Ašœœ˜Kšœ\œ˜cKšœ˜—Kšœ˜Kšœ˜—KšœF˜J—Kšœ˜—K˜—Kšœ0œ˜:K˜K˜.K˜š œœ!œœ#œ˜VKšœ"˜"Kšœ˜K˜—K˜*K˜)˜'šœ œ˜KšœFœ˜LKšœ˜Kšœ˜ Kšœ˜—K˜—K˜&Kšœœ˜K˜—K˜—šœ ™ Kšœœœœ;˜VK˜šžœ˜(K˜)K˜—K˜šž œ˜(Kšœ,˜,Kšœ˜K˜—šž œœ$˜7K˜K˜Kšœœ˜ šžœœ#œ˜4šœ"˜(K–’[node: TextEdit.RefTextNode, index: INT, name: ATOM, value: REF ANY, nChars: INT _ 1, event: TextEdit.Event _ NIL, root: TextEdit.RefTextNode _ NIL]šœAœ=˜—š˜Kšœœ#˜B—K˜—Kšœ=œ˜HK˜1K˜š œœ!œœ#œ˜VKšœ"˜"Kšœ˜K˜—K˜*K˜,K˜&K˜&Kšœœ˜K˜—K˜—šœ ™ Kšœœœœ9˜SK˜šžœ˜'K˜(K˜—K˜šž œ˜'Kšœ+˜+Kšœ˜K˜—šž œœ$˜6K˜Kšœ œ˜K˜Kš œœœœœ˜š žœœœ œœœ˜šœ>œœ˜OKšœœ˜0Kšœ˜—Kšœ˜—Kšœ˜—Kšœ)˜-Kšœ˜—K˜0K˜šœœ!œ˜-Kšœ"˜"Kšœ˜Kšœ˜—K˜*K˜1K˜'K˜&š œœœœœœ˜7K˜=Kšœ œœ)˜?Kšœ˜—K˜6K˜—K˜—šœ™Kšœœœœ7˜PKšœœœœ?˜\K˜šžœ˜&K˜JK˜—K˜šž œ˜&Kšœ*œ˜0Kšœ˜K˜—šžœ˜*Kšœ*œ˜1Kšœ˜K˜—šž œœ'œ˜GK˜Kšœœ˜K˜˜K˜Kšœœ˜Kšœœ˜Kšœ œ˜K˜6KšœœŸ"˜.KšœŸ˜6šžœœœ˜7Kšœœ œœ˜OK˜—Kšœ>œ˜IK˜MKšœœŸ"˜AKšœbœ˜nK˜/K˜šœœ!œ˜-Kšœ%œ˜+Kšœ˜Kšœ"˜"Kšœ˜K˜—K˜*K˜0KšœœŸ˜Kšœ œ œœ˜GKšœ˜ š œœ&œœ˜>šœ"œ˜*Kšœ/œ œ œ ˜Xš žœœœ œœ˜:Kšœœœ˜Kšœ œœ˜šž œœœ˜Kšœœ$˜.šœœ œœ˜&Kšœ.˜.šœ$œ˜,Kšœ˜Kšœ˜Kšœ˜Kšœ ˜ Kšœœ˜ Kšœ˜—Kšœ ˜ Kšœ˜—Kšœ˜—š ž œœœœœ˜4Kšœœ$˜.Kš œœœ8œœœ˜aKšœœ˜(Kšœœ˜&Kšœ ˜ Kšœœ˜Kšœ˜—šœ œ˜Kš œœœœœ œ˜HKšœœœœœœœœ˜WKšœ˜—šœ˜Kšœœ œœœœ œ˜SKšœœœœ œœœ œ˜fKšœ˜—Kšœ˜—Kšœ œ˜Kšœ œ˜ Kšœœ0œ˜Mšœœœ˜Kšœ œ œœ1˜TKšœ œœ/˜EKšœ˜—Kšœœœ œ˜DKšœ˜—šœœœ˜Kšœœ˜(šœ œœŸ˜/Kšœ.˜.Kšœ$œ œ˜