<> <> <> <<>> <> <<>> DIRECTORY IO USING [atom, BreakProc, EndOfStream, GetTokenRope, IDProc, PutFR, RIS, rope, STREAM], LoganBerry USING [AttributeType, AttributeValue, Entry, Error, Open], LoganQuery USING [AttributePatterns, ComplexCursor, NextEntry, QueryEntries, ReadAttributePatterns, SyntaxError], NodeProps USING [GetProp, PutProp], Rope USING [Cat, Concat, ROPE, Size], TextLooks USING [CreateRun], TextNode USING [Body, Ref], TextNodeRegistry USING [ActivityProc, ProcSetRec, Register, SizeProc, TransformProc]; QueryNodeRegister: CEDAR MONITOR IMPORTS IO, LoganBerry, LoganQuery, NodeProps, Rope, TextLooks, TextNodeRegistry = BEGIN ROPE: TYPE ~ Rope.ROPE; Ref: TYPE ~ TextNode.Ref; <> lastq: Ref _ NIL; cursor: REF LoganQuery.ComplexCursor _ NIL; <> FormatProc: TYPE ~ PROC [entry: LoganBerry.Entry] RETURNS [rope: ROPE]; QueryToText: ENTRY PROC [q, p, s: Ref _ NIL, fproc: FormatProc] RETURNS [t: Ref] ~ { <> <> ENABLE LoganBerry.Error => { q.rope _ IO.PutFR["%g\n%g - %g", IO.rope[q.rope], IO.atom[ec], IO.rope[explanation]]; q.runs _ TextLooks.CreateRun[Rope.Size[q.rope]]; GOTO QueryCompleted }; entry: LoganBerry.Entry; IF q=NIL THEN RETURN[NIL]; <> IF q # lastq THEN { -- get new cursor lastq _ q; cursor _ NARROW[NodeProps.GetProp[q, $LBCursor]]; IF cursor = NIL THEN cursor _ QueryToCursor[q]; IF cursor = NIL THEN GOTO QueryCompleted; }; entry _ LoganQuery.NextEntry[cursor: cursor^]; IF entry = NIL THEN GOTO QueryCompleted; <> t _ NEW[TextNode.Body _ q^]; -- t inherits q's properties t.child _ NIL; t.last _ FALSE; t.rope _ fproc[entry]; t.runs _ TextLooks.CreateRun[Rope.Size[t.rope]]; <> t.next _ q; IF s=NIL THEN { IF p=NIL THEN { p _ q; WHILE NOT p.last DO p _ p.next; ENDLOOP; p _ p.next; -- p is now q's parent }; IF p.child#q THEN { s _ p.child; -- get to first sibling WHILE s.next # q DO s _ s.next; ENDLOOP; }; }; IF s#NIL THEN s.next _ t ELSE p.child _ t; EXITS QueryCompleted => { NodeProps.PutProp[q, $Active, NIL]; -- make node inactive RETURN[NIL]; }; }; QueryToCursor: PROC [q: Ref] RETURNS [cursor: REF LoganQuery.ComplexCursor] ~ { query: ROPE = q.rope; cursor _ InitiateQuery[query]; q.rope _ IF cursor = NIL THEN Rope.Concat["Bad Query: ", query] ELSE NIL; q.runs _ TextLooks.CreateRun[Rope.Size[q.rope]]; NodeProps.PutProp[q, $LBCursor, cursor]; }; InitiateQuery: PROC [rope: Rope.ROPE] RETURNS [c: REF LoganQuery.ComplexCursor] ~ { dbname: Rope.ROPE; ap: LoganQuery.AttributePatterns; s: IO.STREAM _ IO.RIS[rope]; dbname _ IO.GetTokenRope[s, IO.IDProc ! IO.EndOfStream => GOTO End].token; ap _ LoganQuery.ReadAttributePatterns[s ! LoganQuery.SyntaxError => GOTO End]; c _ NEW[LoganQuery.ComplexCursor _ LoganQuery.QueryEntries[db: LoganBerry.Open[dbName: dbname], patterns: ap].cursor]; EXITS End => RETURN[NIL]; }; <> EntryToRope: FormatProc ~ { <<[entry: LoganBerry.Entry] RETURNS [rope: ROPE]>> rope _ NIL; FOR l: LoganBerry.Entry _ entry, l.rest WHILE l # NIL DO rope _ IO.PutFR["%g%g: %g\n", IO.rope[rope], IO.atom[l.first.type], IO.rope[l.first.value]]; ENDLOOP; }; LBQueryTransform: TextNodeRegistry.TransformProc = { <<[node: TextNode.Ref, parent: TextNode.Ref, wantFirst: BOOLEAN, clientData: REF ANY] RETURNS [new: TextNode.Ref]>> new _ QueryToText[node, parent, NIL, EntryToRope]; IF new=NIL THEN RETURN[node]; IF NOT wantFirst THEN { <> last: Ref _ new; WHILE last # NIL DO new _ last; last _ QueryToText[node, parent, last, EntryToRope]; ENDLOOP; }; }; LBQuerySize: TextNodeRegistry.SizeProc = { <<[node: TextNode.Ref, clientData: REF ANY] RETURNS [size: INT]>> RETURN[300]; -- a *rough* estimate }; <> tName: LoganBerry.AttributeType = $name; tRname: LoganBerry.AttributeType = $rname; tOffice: LoganBerry.AttributeType = $officenumber; tHome: LoganBerry.AttributeType = $homenumber; tRemarks: LoganBerry.AttributeType = $remarks; LBToTDirEntry: FormatProc ~ { <<[entry: LoganBerry.Entry] RETURNS [rope: ROPE]>> GetAttributeValue: PROC [entry: LoganBerry.Entry, type: LoganBerry.AttributeType] RETURNS [LoganBerry.AttributeValue] ~ { FOR e: LoganBerry.Entry _ entry, e.rest WHILE e # NIL DO IF e.first.type = type THEN RETURN[e.first.value]; ENDLOOP; RETURN[NIL]; }; val: Rope.ROPE; rope _ GetAttributeValue[entry, tName]; val _ GetAttributeValue[entry, tRname]; IF val # NIL THEN rope _ Rope.Cat[rope, " <", val, ">"]; val _ GetAttributeValue[entry, tOffice]; rope _ Rope.Cat[rope, "\t", IF val = NIL THEN "*" ELSE val]; val _ GetAttributeValue[entry, tHome]; rope _ Rope.Cat[rope, "\t", IF val = NIL THEN "*" ELSE val]; val _ GetAttributeValue[entry, tRemarks]; IF val # NIL THEN rope _ Rope.Cat[rope, "\t", val]; }; WPQueryTransform: TextNodeRegistry.TransformProc = { <<[node: TextNode.Ref, parent: TextNode.Ref, wantFirst: BOOLEAN, clientData: REF ANY] RETURNS [new: TextNode.Ref]>> new _ QueryToText[node, parent, NIL, LBToTDirEntry]; IF new=NIL THEN RETURN[node]; IF NOT wantFirst THEN { <> last: Ref _ new; WHILE last # NIL DO new _ last; last _ QueryToText[node, parent, last, LBToTDirEntry]; ENDLOOP; }; }; WPQuerySize: TextNodeRegistry.SizeProc = { <<[node: TextNode.Ref, clientData: REF ANY] RETURNS [size: INT]>> RETURN[300]; -- a *rough* estimate }; TextNodeRegistry.Register[activity: $LBQuery, procs: NEW[TextNodeRegistry.ProcSetRec _ [activityOn: TRUE, transformProc: LBQueryTransform, sizeProc: LBQuerySize, activityProc: NIL]]]; TextNodeRegistry.Register[activity: $WPQuery, procs: NEW[TextNodeRegistry.ProcSetRec _ [activityOn: TRUE, transformProc: WPQueryTransform, sizeProc: WPQuerySize, activityProc: NIL]]]; END.