<< JunoProcViewerImpl.mesa (ex OldParseWindowImpl.mesa)>> <<>> <> <> <> << Maintains a text viewer containing the current set of Juno procedures. Exports procedures that search this list and that append new procedures to it. >> << The viewer has two extra menu buttons:>> <> <> <> << TO FIX: Everything.>> DIRECTORY JunoProcViewer, Rope USING [ROPE, Length, Equal], ViewerClasses USING [Viewer], ViewerOps USING [CreateViewer, DestroyViewer], TiogaOps USING [Ref, CallWithLocks, ViewerDoc, LastWithin, SelectNodes, Break, UnNest, InsertRope, Nest, SelectBranches, Location, FirstChild, SelectPoint, SetSelection, AddLooks, GetRope, GoToNextCharacter, Next]; JunoProcViewerImpl: CEDAR PROGRAM IMPORTS Rope, ViewerOps, TiogaOps EXPORTS JunoProcViewer = BEGIN OPEN Rope, JunoProcViewer; << - - - - PUBLIC PROCEDURES>> TiogaNode: TYPE = TiogaOps.Ref; NewViewer: PUBLIC PROC RETURNS [viewer: Viewer] = BEGIN viewer _ ViewerOps.CreateViewer [flavor: $Text, info: [column: right, iconic: FALSE], paint: TRUE]; -- !! register tioga procs to detect when the contents is edited END; DoInsertText: PROC [viewer: Viewer, n: TiogaNode, text1, text2: ROPE, errBeg, errEnd: INT _ -1] = << To be called through TiogaOps.CallWithLocks. Inserts text1, text2, (and error flag, if errBeg >= 0) at current selection (which should include all of the level >> {TiogaOps.SelectBranches [viewer: viewer, start: n, end: n, level: char, pendingDelete: TRUE]; TiogaOps.InsertRope[text1]; TiogaOps.Break[]; TiogaOps.Nest[]; TiogaOps.InsertRope[text2]; IF errBeg >= 0 THEN {m: TiogaNode _ TiogaOps.FirstChild[n]; nLen: INT = text1.Length; Loc: PROC [pos: INT] RETURNS [TiogaOps.Location] = {RETURN[IF pos < nLen THEN [n, pos] ELSE [m, pos-nLen]]}; locBeg: TiogaOps.Location = Loc[errBeg]; TiogaOps.SelectPoint[viewer, Loc[errEnd]]; TiogaOps.InsertRope["\n"]; TiogaOps.SelectPoint[viewer, locBeg]; TiogaOps.InsertRope["\nERROR: "]; TiogaOps.SetSelection[viewer, [locBeg.node, locBeg.where+1], [locBeg.node, locBeg.where+5]]; TiogaOps.AddLooks[looks: "b"]}}; ParseViewer: PUBLIC PROC [viewer: Viewer, Proc: BranchVisitProc] RETURNS [nerrors: INTEGER] = <> <> BEGIN DoParseViewer: PROC [root: TiogaNode] = {n: TiogaNode _ TiogaOps.FirstChild[root]; nok: INT _ 0; -- number of correct nodes firstError: TiogaOps.Location; nerrors _ 0; IF viewer.destroyed THEN RETURN; -- Should test whether the viewer has been edited since last call WHILE n # NIL DO m: TiogaNode = TiogaOps.FirstChild[n]; text1: ROPE = TiogaOps.GetRope[n]; text2: ROPE = TiogaOps.GetRope[m]; new1, new2: ROPE; errBeg, errEnd: INT; TRUSTED {[new1, new2, errBeg, errEnd] _ Proc[text1, text2]}; IF NOT Rope.Equal[text1, new1] OR NOT Rope.Equal[text2, new2] OR errBeg >= 0 THEN {DoInsertText[viewer, n, new1, new2, errBeg, errEnd]}; IF errBeg >=0 THEN {nerrors _ nerrors+1; IF nerrors = 1 THEN firstError _ [n, errBeg]; IF nerrors > 10 AND nerrors > nok/5 THEN {TiogaOps.SelectPoint[viewer: viewer, caret: [firstError.node, 0]]; TiogaOps.GoToNextCharacter[firstError.where]; RETURN}; n _ TiogaOps.Next[n]}; ENDLOOP}; TiogaOps.CallWithLocks[DoParseViewer, TiogaOps.ViewerDoc[viewer]] END; AddBranch: PUBLIC PROC [viewer: Viewer, text1, text2: ROPE] = <> BEGIN DoAddText: SAFE PROC[root: TiogaOps.Ref] = CHECKED {nd: TiogaOps.Ref; IF viewer.destroyed THEN RETURN; nd _ TiogaOps.LastWithin[TiogaOps.ViewerDoc[viewer]]; TiogaOps.SelectNodes[viewer: viewer, start: nd, end: nd, level: node, caretBefore: FALSE]; TiogaOps.Break[]; TiogaOps.UnNest[]; DoInsertText[viewer, nd, text1, text2]}; TiogaOps.CallWithLocks[DoAddText, TiogaOps.ViewerDoc[viewer]] END; CondDestroyViewer: PROC [viewer: Viewer] = <> {-- Maybe we should we lock the viewer before testing newVersion IF NOT viewer.newVersion THEN ViewerOps.DestroyViewer[viewer]}; END. << - - - - JUNK>> PN2: PROC [n: TiogaNode, pw: Handle] RETURNS [success: BOOL, tree: REF ANY, text1: ROPE, text2: ROPE] = {r: Rope.ROPE; vc: VerdictAndCulprit; errorMessage: ROPE _ NIL; text1 _ TiogaOps.GetRope[n]; text2 _ TiogaOps.GetRope[TiogaOps.FirstChild[n]]; -- next three lines try to skip parsing if old parsed result is present in pw.contents: { l: LIST OF NodeContent _ pw.content ; WHILE l # NIL AND NOT(Rope.Equal[l.first.text1, text1] AND Rope.Equal[l.first.text2, text2]) DO l _ l.rest ENDLOOP ; IF l # NIL THEN { success _ TRUE ; tree _ l.first.tree ; text1 _ l.first.text1; text2 _ l.first.text2 ; RETURN } }; IF ~ pw.contentValid THEN RETURN; pw.ph.in.in _ IO.RIS[Rope.Cat[text1, text2, " "]]; pw.ph.in.eof _ FALSE; pw.ph.in.error _ NIL; pw.ph.in.Lex[]; IF pw.ph.in.eof THEN {success _ TRUE; tree _ text1 _ text2 _ NIL; RETURN}; pw.ph.Parse[]; pw.ph.result _ tree _ CONS[pw.ph.result, NIL]; -- necessary because WellFormed and Unparse work on the CAR of their argument -- and ignore the cdr. IF pw.ph.error = NIL AND pw.ph.eof THEN {vc _ pw.WellFormed[pw.ph.result]; IF vc.verdict # Yes THEN errorMessage _ "Not a WFF" ELSE {vc.culprit _ NIL; errorMessage _ NIL}} ELSE {vc.culprit _ NIL; errorMessage _ IF pw.ph.error # NIL THEN pw.ph.error ELSE "Bad Syntax"}; r _ Unparser.Unparse[pw.ph.result, vc.culprit, 57, pw.ph.table, pw.ph.openCount]; --! change "57" to "width of window" tree _ NARROW[pw.ph.result, LIST OF REF ANY].first; IF pw.ph.error # NIL OR ~pw.ph.eof THEN {r _ Rope.Cat[r, " \000", Rope.FromRefText[pw.ph.in.buf], "\000"]; WHILE ~ IO.EndOf[pw.ph.in.in] DO r _ Rope.Cat[r, Rope.FromChar[IO.GetChar[pw.ph.in.in]]] ENDLOOP}; {i: INT _ r.SkipTo[0, "\000"]; j: INT; endOfHeader: INT = r.SkipTo[0, "\n"]; firstLine: Rope.ROPE = r.Substr[0, endOfHeader]; restOfLines: Rope.ROPE = IF endOfHeader = r.Length THEN NIL ELSE r.Substr[endOfHeader + 1]; Foo: SAFE PROC[root: TiogaOps.Ref] = TRUSTED {m: TiogaNode = IF TiogaOps.FirstChild[n] = NIL THEN n ELSE TiogaOps.FirstChild[n]; TiogaOps.SelectNodes[viewer: pw.viewer, start:n, end:m, pendingDelete: TRUE, level:char]; IF i = r.Length[] THEN {TiogaOps.InsertRope[firstLine]; TiogaOps.Break[]; TiogaOps.Nest[]; TiogaOps.InsertRope[restOfLines]} ELSE {j _ r.SkipTo[i + 1, "\000"]; TiogaOps.InsertRope[Rope.Cat[r.Substr[0, i], r.Substr[i+1, j - i - 1], r.Substr[j+1]]]; TiogaOps.SetSelection[pw.viewer, [n, i], [n, j - 1]]}}; TiogaOps.CallWithLocks[Foo, TiogaOps.ViewerDoc[pw.viewer]]; success _ (errorMessage = NIL); text1 _ firstLine; text2 _ restOfLines}};