DIRECTORY Ascii USING [Lower], Rope USING [Fetch, ROPE, Size, Substr], SpellingLooks USING [Wordlich], RunReader USING [BumpIndex, Create, GetIndex, MergedBackwards, MergedGet, Ref, SetPosition], SpellingToolShared, SpellingWordMap USING [MapWordsInRope, MapWordsInRopeBackward], TextLooks USING [CreateRun, Looks, noLooks, Runs, Substr], TextNode USING [NarrowToTextNode, NodeRuns, Ref, RefTextNode], TiogaOps USING [FirstSibling, GetRope, GetSelection, GetStyle, LastWithin, Lock, LockSel, NoSelection, Root, SelectionGrain, SelectionRoot, StepBackward, StepForward, Unlock, UnlockSel], TiogaOpsDefs USING [Location, Ref, Viewer]; SpellingToolSharedImpl: CEDAR MONITOR IMPORTS Ascii, Rope, RunReader, SpellingLooks, SpellingWordMap, TextLooks, TextNode, TiogaOps EXPORTS SpellingToolShared = BEGIN OPEN SpellingToolShared; ROPE: TYPE = Rope.ROPE; CorrectTiogaOpsCallWithLocks: PUBLIC PROC [proc: PROC [root: TiogaOpsDefs.Ref], root: TiogaOpsDefs.Ref _ NIL] = { lockedSel, lockedDoc: BOOL _ FALSE; Cleanup: PROC = { IF lockedSel THEN { TiogaOps.UnlockSel; lockedSel _ FALSE; }; IF lockedDoc THEN { TiogaOps.Unlock[root]; lockedDoc _ FALSE; }; }; { ENABLE UNWIND => Cleanup; TiogaOps.LockSel; lockedSel _ TRUE; IF root=NIL AND (root _ TiogaOps.SelectionRoot[])=NIL THEN ERROR TiogaOps.NoSelection; TiogaOps.Lock[root]; lockedDoc _ TRUE; proc[root]; Cleanup[]; }; }; wordBuffer: REF TEXT _ NEW[TEXT[256]]; GetLooks: PROC [tiogaOpsNode: TiogaOpsDefs.Ref] RETURNS [runs: TextLooks.Runs] = { textNode: TextNode.Ref; refTextNode: TextNode.RefTextNode; TRUSTED {textNode _ LOOPHOLE[tiogaOpsNode]}; refTextNode _ TextNode.NarrowToTextNode[textNode]; runs _ IF refTextNode # NIL THEN TextNode.NodeRuns[refTextNode] ELSE NIL; }; emptyLooks: TextLooks.Runs _ TextLooks.CreateRun[len: 0]; MapWordsInSelection: PUBLIC ENTRY PROC [start, end: TiogaOpsDefs.Location, f: PROC [REF TEXT] RETURNS [BOOL], forwards: BOOL] RETURNS [premature: BOOL _ FALSE, wordStart, wordEnd: TiogaOpsDefs.Location] = { ENABLE UNWIND => NULL; loc: TiogaOpsDefs.Location _ IF forwards THEN start ELSE end; nodeLooksReader: RunReader.Ref _ RunReader.Create[]; MapNode: PROC [start: TiogaOpsDefs.Location, endPlusOne: INT, word: REF TEXT, f: PROC [REF TEXT] RETURNS [BOOL], forwards: BOOL] RETURNS [premature: BOOL _ FALSE, wordStart, wordEnd: TiogaOpsDefs.Location] = { nodeStyle: ROPE _ TiogaOps.GetStyle[start.node]; nodeRope: ROPE _ TiogaOps.GetRope[start.node]; nodeLooks: TextLooks.Runs _ GetLooks[start.node]; index, size, lowest: INT; IF endPlusOne = -1 THEN endPlusOne _ LAST[INT]; endPlusOne _ MIN[endPlusOne, nodeRope.Size[]]; IF endPlusOne <= start.where THEN RETURN; size _ endPlusOne - start.where; IF ~(start.where = 0 AND endPlusOne = nodeRope.Size[]) THEN { nodeRope _ nodeRope.Substr[start.where, size]; nodeLooks _ nodeLooks.Substr[start.where, size]}; IF forwards THEN index _ 0 ELSE index _ size; nodeLooksReader.SetPosition[nodeLooks, index]; SELECT forwards FROM TRUE => DO length, next: INT; rope: ROPE; looks: TextLooks.Looks _ TextLooks.noLooks; IF nodeLooksReader.GetIndex[] # index THEN ERROR; IF index >= size THEN EXIT; IF nodeLooks # NIL THEN [length, looks] _ RunReader.MergedGet[nodeLooksReader] ELSE {length _ size; nodeLooksReader.BumpIndex[size]}; next _ index + length; rope _ nodeRope.Substr[lowest _ index, length]; IF SpellingLooks.Wordlich[nodeStyle, looks] THEN { [premature, wordStart.where, wordEnd.where, word] _ SpellingWordMap.MapWordsInRope[rope, word, f]; IF premature THEN EXIT}; index _ next; ENDLOOP; FALSE => DO length, next: INT; rope: ROPE; looks: TextLooks.Looks _ TextLooks.noLooks; IF nodeLooksReader.GetIndex[] # index THEN ERROR; IF index <= 0 THEN EXIT; IF nodeLooks # NIL THEN [length, looks] _ RunReader.MergedBackwards[nodeLooksReader] ELSE {length _ size; nodeLooksReader.BumpIndex[-size]}; next _ index - length; rope _ nodeRope.Substr[lowest _ next, length]; IF SpellingLooks.Wordlich[nodeStyle, looks] THEN { [premature, wordStart.where, wordEnd.where, word] _ SpellingWordMap.MapWordsInRopeBackward[rope, word, f]; IF premature THEN EXIT}; index _ next; ENDLOOP; ENDCASE => ERROR; wordStart.node _ start.node; wordStart.where _ wordStart.where + lowest + start.where; wordEnd.node _ start.node; wordEnd.where _ wordEnd.where + lowest + start.where - 1; }; IF forwards THEN DO [premature, wordStart, wordEnd] _ MapNode[loc, IF loc.node = end.node THEN end.where+1 ELSE -1, wordBuffer, f, TRUE]; IF premature THEN RETURN; IF loc.node = end.node OR loc.node = NIL THEN RETURN; loc.node _ TiogaOps.StepForward[loc.node]; loc.where _ 0; ENDLOOP ELSE DO IF loc.node = start.node THEN loc.where _ start.where ELSE loc.where _ 0; [premature, wordStart, wordEnd] _ MapNode[loc, IF loc.node = end.node THEN end.where+1 ELSE -1, wordBuffer, f, FALSE]; IF premature THEN RETURN; IF loc.node = start.node OR loc.node = NIL THEN RETURN; loc.node _ TiogaOps.StepBackward[loc.node]; loc.where _ 0; ENDLOOP }; ProcessSelection: PUBLIC PROC [forceEOD: BOOL _ FALSE, defEOD: BOOL _ TRUE, forwards: BOOL] RETURNS [s: Selection, wasExtended: BOOL _ FALSE] = { selViewer: TiogaOpsDefs.Viewer; selStart, selEnd: TiogaOpsDefs.Location; selLevel: TiogaOps.SelectionGrain; selCaretBefore, selPendingDelete: BOOL; [selViewer, selStart, selEnd, selLevel, selCaretBefore, selPendingDelete] _ TiogaOps.GetSelection[]; s _ NEW[SelectionRec]; s.viewer _ selViewer; s.start _ selStart; s.end _ selEnd; s.level _ selLevel; s.caretBefore _ selCaretBefore; s.pendingDelete _ selPendingDelete; IF forceEOD OR (defEOD AND (selLevel = point OR ((selLevel = char) AND (selStart.node = selEnd.node) AND (selStart.where = selEnd.where)))) THEN { IF forwards THEN { s.end.node _ TiogaOps.LastWithin[TiogaOps.Root[s.start.node]]; s.end.where _ (TiogaOps.GetRope[s.end.node]).Size[]-1; } ELSE { s.start.node _ FirstWithin[TiogaOps.Root[s.start.node]]; s.start.where _ 0; }; CheckMiddleOfWord[s]; wasExtended _ TRUE; }; }; FirstWithin: PUBLIC PROC [r: TiogaOpsDefs.Ref] RETURNS [first: TiogaOpsDefs.Ref] = { child: TiogaOpsDefs.Ref; first _ r; DO child _ TiogaOps.FirstSibling[first]; IF child = NIL THEN RETURN; first _ child; ENDLOOP; }; CheckMiddleOfWord: PUBLIC PROC[s: Selection] = { IF s.start.where > 0 THEN { r: ROPE _ TiogaOps.GetRope[s.start.node]; IF Ascii.Lower[r.Fetch[s.start.where-1]] IN ['a..'z] THEN WHILE s.start.where < r.Size[] AND Ascii.Lower[r.Fetch[s.start.where]] IN ['a..'z] DO s.start.where _ s.start.where + 1; ENDLOOP; }; }; END. SpellingToolSharedImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Last Edited by: Nix, December 9, 1983 2:52 pm Michael Plass, January 23, 1986 2:50:21 pm PST Rick Beach, May 2, 1985 3:10:55 pm PDT Spreitzer, February 26, 1985 2:37:59 pm PST We know this is OK because TiogaExtraOpsImpl says (TiogaOpsDefs.)NodeBody = TextNode.Body Maps the given procedure f over the words in the selection, returning as soon as f returns TRUE. Maps the given procedure f over the words in a single Tioga node, returning as soon as f returns TRUE. Analyzes the current selection and returns a selection record that describes it. If forceEOD is true, then the selection record returned always describes a selection from the beginning of the current selection to the end of the document, even if the user only had one word selected. If defEOD is TRUE, then this sort of selection is returned only when the user has a point or single character selection, otherwise the user's actual selection is returned. CHANGE LOG Spreitzer, February 26, 1985 1:09:03 pm PST Added looks rule to definition of `word'. changes to: DIRECTORY, SpellingToolSharedImpl, GetLooks, MapWordsInSelection Michael Plass, January 23, 1986 2:50:02 pm PST Fixed off-by-one bug. changes to: MapWordsInSelection Κ5˜codešœ™Kšœ Οmœ1™Kšœ žœ¬˜ΊKšœ žœ˜+—K˜KšΡblnœžœžœ˜&KšžœV˜]Kšžœ˜šœžœžœ˜ Kšžœžœžœ˜K˜š Οnœžœžœžœ4žœ˜qKšœžœžœ˜#š œžœ˜šžœ žœ˜Kšœ˜Kšœ žœ˜Kšœ˜—šžœ žœ˜Kšœ˜Kšœ žœ˜Kšœ˜—K˜—˜Kšžœžœ ˜Kšœžœ˜#š žœžœžœ#žœžœ˜;Kšžœ˜—Kšœ!žœ˜&K˜ K˜ K˜—K˜—K˜Kš œ žœžœžœžœ˜&K˜š œžœ"žœ˜RKšœ˜Kšœ"˜"šžœ žœ˜,K™Y—Kšœ2˜2Kš œžœžœžœ žœžœ˜IK˜K˜9K˜—š œžœžœžœ(žœžœžœžœžœ žœžœ žœžœ0˜ΞKšœa™aKšžœžœžœ˜Kšœžœ žœžœ˜=K˜4šΟbœ˜šžœ˜#Kšœ žœ˜Kšœžœžœ˜Kš œžœžœžœžœžœ˜"Kšœ žœ˜—šžœ žœžœ˜!Kšœ.˜.—Kšœf™fKšœ žœ!˜0Kšœ žœ ˜.Kšœ1˜1Kšœžœ˜Kšžœžœžœžœ˜/Kšœ žœ˜.Kšžœžœžœ˜)K˜ šžœžœžœ˜=K˜.Kšœ1˜1—Kšžœ žœ žœ˜-Kšœ.˜.šžœ ž˜šžœž˜ Kšœžœ˜Kšœžœ˜ K˜+Kšžœ$žœžœ˜1Kšžœžœžœ˜šžœ ž˜Kšžœ8˜˜BKšžœ3˜7—Kšœ˜Kšœ.˜.šžœ*žœ˜2Kšœj˜jKšžœ žœžœ˜—K˜ Kšžœ˜—Kšžœžœ˜—K˜K˜9K˜K˜9K˜K˜—šžœ ž˜šž˜šœ"˜"Kš œ žœžœ žœžœ˜S—Kšžœ žœžœ˜Kš žœžœ žœžœžœ˜5K˜*K˜Kšž˜——šž˜šž˜šžœž˜Kšœ˜—šžœ˜K˜—šœ"˜"Kš œ žœžœ žœžœ˜T—Kšžœ žœžœ˜Kš žœžœ žœžœžœ˜7Kšœ+˜+Kšœ˜Kšž˜—K˜—K˜K˜—K˜šΠanΟažœžœ žœžœ žœžœ žœžœžœžœ˜‘KšœΘ™ΘKšœ˜Kšœ(˜(K˜"Kšœ"žœ˜'K˜dKšœžœ˜Kšœ˜Kšœ˜Kšœ˜K˜Kšœ˜Kšœ#˜#šžœ žœ žœžœžœ!žœ$žœ˜™šžœ žœ˜K˜>K˜6K˜—šžœ˜K˜8K˜K˜—Kšœ˜Kšœžœ˜K˜—K˜K˜K˜—š  œžœžœžœ˜UK˜K˜ šž˜Kšœ%˜%Kšžœ žœžœžœ˜K˜Kšžœ˜—K˜K˜K˜—š œžœžœ˜0šžœžœ˜Kšœžœ"˜)šžœ'žœ žœ˜:šžœžœ%žœ ž˜VK˜"Kšžœ˜——K˜—K˜——K˜Kšžœ˜K™Kšžœž™ K™™+K™)Kšœ Οr@™L—™.K™Kšœ €™—K™—…—P&—