DIRECTORY TEditSelection, Atom, TiogaAccess, TiogaOps, Rope, NodeProps, TEditInput, ViewerClasses, NodePropsExtras, RefText, RopeEdit, RuntimeError, TEditSelectionOps, ViewerOps, TextNode, TEditDocument; EditPropertiesImpl: CEDAR PROGRAM IMPORTS TEditSelection, Atom, TiogaAccess, TiogaOps, Rope, NodeProps, TEditInput, NodePropsExtras, RefText, RopeEdit, RuntimeError, TEditSelectionOps, ViewerOps, TextNode ~ BEGIN ROPE: TYPE ~ Rope.ROPE; TranslateToOpenProperties: PROC [reader: TiogaAccess.Reader, writer: TiogaAccess.Writer] ~ { t: TiogaAccess.TiogaChar _ [charSet: 0, char: 0C, looks: ALL[FALSE], format: NIL, comment: FALSE, endOfNode: FALSE, deltaLevel: 0, propList: NIL]; node: TiogaAccess.TiogaChar _ [charSet: 0, char: 15C, looks: ALL[FALSE], format: $code, comment: FALSE, endOfNode: TRUE, deltaLevel: 0, propList: NIL]; nest: TiogaAccess.TiogaChar _ [charSet: 0, char: 15C, looks: ALL[FALSE], format: $code, comment: FALSE, endOfNode: TRUE, deltaLevel: 1, propList: NIL]; outc: TiogaAccess.TiogaChar _ [charSet: 0, char: 0C, looks: ALL[FALSE], format: NIL, comment: FALSE, endOfNode: FALSE, deltaLevel: 0, propList: NIL]; PutRope: PROC [rope: ROPE] ~ { FOR i: INT IN [0..Rope.Size[rope]) DO outc.char _ Rope.Fetch[rope, i]; TiogaAccess.Put[writer, outc]; ENDLOOP; }; PutOctal: PROC [b: [0..256)] ~ { outc.char _ '0+b/64; TiogaAccess.Put[writer, outc]; outc.char _ '0+(b/8) MOD 8; TiogaAccess.Put[writer, outc]; outc.char _ '0+b MOD 8; TiogaAccess.Put[writer, outc]; }; PutPropName: PROC [atom: ATOM] ~ { save: TiogaAccess.Looks _ outc.looks; outc.looks['n] _ TRUE; PutRope[Atom.GetPName[atom]]; outc.looks _ save; PutRope[": "]; }; PutKey: PROC [rope: ROPE] ~ { save: TiogaAccess.Looks _ outc.looks; outc.looks['k] _ TRUE; outc.looks['b] _ TRUE; PutRope[rope]; outc.looks _ save; }; PutProperties: PROC [propList: Atom.PropList] ~ { FOR each: Atom.PropList _ propList, each.rest UNTIL each = NIL DO key: ATOM ~ NARROW[each.first.key]; PutProperty[key, each.first.val]; ENDLOOP; }; PutProperty: PROC [key: ATOM, value: REF] ~ { IF value # NIL THEN { rope: ROPE ~ TiogaAccess.GetExternalProp[key, value]; PutPropName[key]; IF rope = NIL OR NodePropsExtras.Is[key, $ClientOnly] THEN { save: TiogaAccess.Looks _ outc.looks; outc.looks['c] _ TRUE; PutRope["(opaque)"]; outc.looks _ save; node.propList _ CONS[NEW[Atom.DottedPairNode _ [key: $OpaqueValue, val: value]], node.propList]; TiogaAccess.Put[writer, node]; node.propList _ node.propList.rest; } ELSE { PutRope[rope]; TiogaAccess.Put[writer, node]; }; }; }; TranslateNodeContents: PROC ~ { UNTIL t.endOfNode DO looks: TiogaAccess.Looks ~ t.looks; propList: Atom.PropList ~ t.propList; IF t.charSet = 0 AND t.char IN [' ..'~] THEN { PutPropName[$Text]; WHILE NOT t.endOfNode AND t.charSet = 0 AND t.char IN [' ..'~] AND t.looks=looks AND t.propList = propList DO save: TiogaAccess.Looks _ outc.looks; outc.char _ t.char; outc.looks['o] _ TRUE; TiogaAccess.Put[writer, outc]; outc.looks _ save; t _ TiogaAccess.Get[reader]; ENDLOOP; } ELSE { PutPropName[$Char]; PutRope["("]; PutOctal[t.charSet]; PutRope["|"]; PutOctal[ORD[t.char]]; PutRope[")"]; t _ TiogaAccess.Get[reader]; }; TiogaAccess.Put[writer, node]; IF looks # ALL[FALSE] THEN { TiogaAccess.Nest[writer, 1]; PutKey["LOOKS"]; PutRope["("]; FOR c: CHAR IN TiogaAccess.Look DO IF looks[c] THEN {outc.char _ c; TiogaAccess.Put[writer, outc]}; ENDLOOP; PutRope[")"]; TiogaAccess.Put[writer, node]; TiogaAccess.Nest[writer, -1]; }; IF propList # NIL THEN { TiogaAccess.Nest[writer, 1]; PutProperties[propList]; TiogaAccess.Nest[writer, -1]; }; ENDLOOP; }; UNTIL TiogaAccess.EndOf[reader] DO t _ TiogaAccess.Get[reader]; PutKey["BEGIN NODE"]; TiogaAccess.Put[writer, nest]; IF NOT t.endOfNode THEN { PutKey["CONTENTS"]; TiogaAccess.Put[writer, nest]; TranslateNodeContents[]; TiogaAccess.Nest[writer, -1]; }; PutKey["PROPERTIES"]; TiogaAccess.Put[writer, nest]; PutProperty[$Comment, IF t.comment THEN NodeProps.true ELSE NodeProps.false]; PutProperty[$Format, t.format]; PutProperties[t.propList]; TiogaAccess.Nest[writer, -1]; PutKey["END NODE"]; TiogaAccess.Put[writer, node]; TiogaAccess.Nest[writer, t.deltaLevel-1]; ENDLOOP; }; Cant: ERROR ~ CODE; TranslateFromOpenProperties: PROC [reader: TiogaAccess.Reader, writer: TiogaAccess.Writer] ~ { Must: PROC [assertion: BOOL] ~ {IF NOT assertion THEN Cant[]}; break: TiogaAccess.TiogaChar _ [charSet: 0, char: 0C, looks: ALL[FALSE], format: NIL, comment: FALSE, endOfNode: FALSE, deltaLevel: 0, propList: NIL]; Match: PROC [rope: ROPE] RETURNS [BOOL] ~ { targetLen: INT ~ Rope.Size[rope]; input: ROPE ~ TiogaAccess.PeekRope[reader]; matchLen: INT ~ Rope.Run[s1: rope, s2: input, case: TRUE]; IF matchLen=targetLen THEN { FOR i: INT IN [0..targetLen) DO [] _ TiogaAccess.Get[reader] ENDLOOP; RETURN [TRUE]; }; RETURN [FALSE]; }; level: INT _ 0; MatchBreak: PROC RETURNS [BOOL] ~ { IF TiogaAccess.Peek[reader].endOfNode THEN { break _ TiogaAccess.Get[reader]; level _ level + break.deltaLevel; RETURN [TRUE]; }; RETURN [FALSE]; }; MustNest: PROC ~ {Must[MatchBreak[] AND break.deltaLevel = 1]}; GetOctal3: PROC RETURNS [[0..256)] ~ { v: CARDINAL _ 0; FOR i: NAT IN [0..3) DO t: TiogaAccess.TiogaChar _ TiogaAccess.Get[reader]; Must[t.char IN ['0..'8) AND t.charSet = 0]; v _ v*8 + (t.char-'0); ENDLOOP; Must[v IN [0..256)]; RETURN [v]; }; RopeToEnd: PROC RETURNS [ROPE] ~ { rope: ROPE _ TiogaAccess.PeekRope[reader]; FOR i: INT IN [0..Rope.Size[rope]) DO [] _ TiogaAccess.Get[reader] ENDLOOP; RETURN [rope]; }; ParseProp: PROC RETURNS [Atom.DottedPairNode] ~ { keyText: REF TEXT ~ RefText.ObtainScratch[100]; t: TiogaAccess.TiogaChar _ TiogaAccess.Get[reader]; key: ATOM _ NIL; rope: ROPE _ NIL; value: REF; WHILE t.charSet = 0 AND RopeEdit.AlphaNumericChar[t.char] DO Must[keyText.length < keyText.maxLength]; keyText[keyText.length] _ t.char; keyText.length _ keyText.length + 1; t _ TiogaAccess.Get[reader]; ENDLOOP; Must[keyText.length > 0]; Must[t.charSet = 0 AND t.char = ':]; Must[Match[" "]]; rope _ RopeToEnd[]; Must[MatchBreak[]]; key _ Atom.MakeAtomFromRefText[keyText]; value _ Atom.GetPropFromList[break.propList, $OpaqueValue]; IF value = NIL THEN value _ TiogaAccess.GetInternalProp[key, rope]; RefText.ReleaseScratch[keyText]; RETURN [[key: key, val: value]]; }; UNTIL TiogaAccess.EndOf[reader] DO IF Match["BEGIN NODE"] THEN { node: TiogaAccess.TiogaChar _ [charSet: 0, char: 15C, looks: ALL[FALSE], format: NIL, comment: FALSE, endOfNode: TRUE, deltaLevel: 0, propList: NIL]; level _ 0; MustNest[]; IF Match["CONTENTS"] THEN { MustNest[]; WHILE level >= 2 DO outc: TiogaAccess.TiogaChar _ [charSet: 0, char: 0C, looks: ALL[FALSE], format: NIL, comment: FALSE, endOfNode: FALSE, deltaLevel: 0, propList: NIL]; rope: ROPE _ NIL; Must[level = 2]; IF Match["Text: "] THEN rope _ RopeToEnd[] ELSE { Must[Match["Char: ("]]; outc.charSet _ GetOctal3[]; Must[Match["|"]]; rope _ Rope.FromChar[VAL[GetOctal3[]]]; Must[Match[")"]]; }; Must[MatchBreak[]]; WHILE level >= 3 DO Must[level = 3]; IF Match["LOOKS("] THEN { t: TiogaAccess.TiogaChar _ TiogaAccess.Peek[reader]; WHILE t.charSet = 0 AND t.char IN TiogaAccess.Look DO t _ TiogaAccess.Get[reader]; outc.looks[t.char] _ TRUE; t _ TiogaAccess.Peek[reader]; ENDLOOP; Must[Match[")"]]; Must[MatchBreak[]]; } ELSE { pair: Atom.DottedPairNode ~ ParseProp[]; outc.propList _ CONS[NEW[Atom.DottedPairNode _ pair], outc.propList]; }; ENDLOOP; IF rope # NIL THEN { action: Rope.ActionType = { outc.char _ c; TiogaAccess.Put[writer, outc] }; [] _ Rope.Map[base: rope, action: action]; }; ENDLOOP; }; IF Match["PROPERTIES"] THEN { MustNest[]; WHILE level >= 2 DO pair: Atom.DottedPairNode; Must[level = 2]; pair _ ParseProp[]; SELECT pair.key FROM $Comment => WITH pair.val SELECT FROM b: REF BOOL => node.comment _ b^ ENDCASE; $Format => WITH pair.val SELECT FROM a: ATOM => node.format _ a ENDCASE; ENDCASE => node.propList _ CONS[NEW[Atom.DottedPairNode _ pair], node.propList]; ENDLOOP; }; Must[level = 1]; Must[Match["END NODE"]]; Must[MatchBreak[]]; node.deltaLevel _ level; TiogaAccess.Put[writer, node]; } ELSE { Must[TiogaAccess.CopyNode[writer, reader].nodeEnd]; }; ENDLOOP; }; MakeNodeSelection: PROC ~ { tSel: TEditDocument.Selection; IF TEditSelection.pSel=NIL OR TEditSelection.pSel.viewer=NIL THEN RETURN; tSel _ TEditSelection.Alloc[]; TEditSelection.Copy[source: TEditSelection.pSel, dest: tSel]; SELECT tSel.granularity FROM point, char, word => { tSel.start.pos.where _ 0; tSel.end.pos.where _ TextNode.EndPos[tSel.end.pos.node]; tSel.granularity _ node; }; ENDCASE => NULL; TEditSelection.MakeSelection[new: tSel]; TEditSelection.Free[tSel] }; OpenPropertiesOp: TEditInput.CommandProc ~ { OpenProperties: PROC [root: TiogaOps.Ref] ~ { reader: TiogaAccess.Reader _ NIL; writer: TiogaAccess.Writer _ NIL; MakeNodeSelection[]; reader _ TiogaAccess.FromSelection[]; writer _ TiogaAccess.Create[]; TranslateToOpenProperties[reader, writer]; TiogaAccess.WriteSelection[writer]; }; TiogaOps.CallWithLocks[OpenProperties]; quit _ TRUE; }; ClosePropertiesOp: TEditInput.CommandProc ~ { error: {none, cant, uncaught} _ none; errorPosition: INT _ 0; CloseProperties: PROC [root: TiogaOps.Ref] ~ { reader: TiogaAccess.Reader _ NIL; writer: TiogaAccess.Writer _ NIL; MakeNodeSelection[]; reader _ TiogaAccess.FromSelection[]; writer _ TiogaAccess.Create[]; TranslateFromOpenProperties[reader, writer ! Cant => {errorPosition _ TiogaAccess.GetPosition[reader]} ]; TiogaAccess.WriteSelection[writer]; }; TiogaOps.CallWithLocks[CloseProperties ! Cant => {error _ cant; CONTINUE}; RuntimeError.UNCAUGHT => {error _ uncaught; CONTINUE}; ]; SELECT error FROM none => NULL; cant => { TEditSelectionOps.ShowGivenPosition[viewer: viewer, pos: errorPosition, skipCommentNodes: TRUE]; ViewerOps.BlinkViewer[viewer, 200]; }; uncaught => CloseProperties[NIL]; -- do without lock for easy debug ENDCASE => ERROR; quit _ TRUE; }; TEditInput.Register[name: $OpenProperties, proc: OpenPropertiesOp, before: TRUE]; TEditInput.Register[name: $CloseProperties, proc: ClosePropertiesOp, before: TRUE]; END. ΤEditPropertiesImpl.mesa Copyright c 1986 by Xerox Corporation. All rights reserved. Michael Plass, October 28, 1986 1:00:59 pm PST Emit a run of printable ascii characters, all with the same looks and properties Emit a single XC character Emit the looks that apply to the previous text or character Emit the properties that apply to the previous text or character PROC [viewer: ViewerClasses.Viewer _ NIL] RETURNS [recordAtom: BOOL _ TRUE, quit: BOOL _ FALSE]; ΚΝ˜™Icodešœ Οmœ1™Kš œ=žœžœ žœ žœ žœžœ˜–š  œžœžœžœžœ˜+Kšœ žœ˜!K•StartOfExpansionO[s1: ROPE, pos1: INT _ 0, s2: ROPE, pos2: INT _ 0, case: BOOL _ TRUE]šœžœ ˜+Kšœ žœ'žœ˜:šžœžœ˜Kš žœžœžœžœžœ˜EKšžœžœ˜Kšœ˜—Kšžœžœ˜Kšœ˜—Kšœžœ˜š  œžœžœžœ˜#šžœ$žœ˜,Kšœ ˜ Kšœ!˜!Kšžœžœ˜Kšœ˜—Kšžœžœ˜Kšœ˜—Kš œžœžœ˜?š  œžœžœ˜&Kšœžœ˜šžœžœžœž˜Kšœ3˜3Kšœ žœ žœ˜+Kšœ˜Kšžœ˜—Kšœžœ ˜Kšžœ˜ Kšœ˜—š  œžœžœžœ˜"Kšœžœ ˜*Kš žœžœžœžœžœ˜KKšžœ˜Kšœ˜—š  œžœžœ˜1Kšœ žœžœ˜/Kšœ3˜3Kšœžœžœ˜Kšœžœžœ˜Kšœžœ˜ šžœžœ#ž˜