DIRECTORY Dictionary, Atom, BasicTime, Convert, IO, IOTioga, Menus USING [MenuProc], RefTab USING [Create, Erase, Fetch, Ref, Store], Rope, Rosary, SpellingToolServices, SpellingToolShared USING [Selection, ProcessSelection, ToRope], TextEdit, TextLooks, Tioga, TiogaOps USING [CallWithLocks, NoSelection], TiogaOpsDefs USING [Ref]; SpellingToolServicesImpl: CEDAR MONITOR IMPORTS Dictionary, Atom, BasicTime, Convert, IO, IOTioga, RefTab, Rope, Rosary, SpellingToolShared, TextEdit, TextLooks, TiogaOps EXPORTS SpellingToolServices = { STREAM: TYPE = IO.STREAM; ROPE: TYPE = Rope.ROPE; AtomList: TYPE = LIST OF ATOM; AtomListList: TYPE = LIST OF AtomList; definitionCaveat: BOOL ¬ FALSE; totalDefinitionsCnt, totalDefinitionsWorkedCount: INT ¬ 0; permMessage: STREAM ¬ NIL; dictionary: ATOM = $AmericanHeritage; checker: ATOM = $Proofreader; morph: ATOM = $EnglishMorph; conjug: ATOM = NIL; looksTranslator: RefTab.Ref = RefTab.Create[]; InitializeDictionaryServer: PUBLIC PROC [outputStream: STREAM] = { ENABLE { UNWIND => {}; Dictionary.Error => { SELECT problem FROM courier => PutCourierError[permMessage, explanation]; service => PutServiceError[permMessage, explanation]; ENDCASE => ERROR; CONTINUE; -- was missing so error was not really being caught }; }; permMessage ¬ outputStream; SetupLooksTranslator[]; }; DefinitionButton: PUBLIC Menus.MenuProc = TRUSTED { theWord, wordNoBlank: ROPE; DictionaryCommand: PRIVATE PROC [theWord: ROPE] = TRUSTED { entryHandle, item: ROPE ¬ NIL; definition: Dictionary.Definition; IF theWord.Length[] # 0 THEN definition ¬ Dictionary.GetDefinition[theWord, dictionary ! Dictionary.Error => {definition.definition ¬ NIL; CONTINUE}]; IF definition.definition.Length[] # 0 THEN { PutWithRuns[permMessage, definition.definition, definition.looks]; IO.PutRope[permMessage, "\n"]; totalDefinitionsWorkedCount ¬ totalDefinitionsWorkedCount + 1} ELSE IO.PutRope[permMessage, "not found\n"]; }; { Locker: PRIVATE PROC [root: TiogaOpsDefs.Ref] = TRUSTED { now: BasicTime.Unpacked ~ BasicTime.Unpack[BasicTime.Now[]]; s: SpellingToolShared.Selection ¬ SpellingToolShared.ProcessSelection[FALSE,TRUE, TRUE].s; wordNoBlank ¬ SpellingToolShared.ToRope[s]; IF Rope.Length[wordNoBlank]=0 THEN IO.PutRope[permMessage, "No word has been selected.\n"] ELSE { IF now.month=April AND now.day=1 AND now.second<30 THEN wordNoBlank ¬ "Fool"; IO.PutF1[permMessage, "Looking up the definition of \"%g\"...\n", IO.rope[wordNoBlank]]; theWord ¬ wordNoBlank; -- Bug in Dictionary server requires it. }; }; IF ~definitionCaveat THEN IO.PutRope[permMessage, "Warning: the definition facility often fails to work.\n"]; TiogaOps.CallWithLocks[Locker ! TiogaOps.NoSelection => { GOTO dictionaryBlownAway}]; definitionCaveat ¬ TRUE; IF theWord = NIL THEN { RETURN; }; totalDefinitionsCnt ¬ totalDefinitionsCnt + 1; DictionaryCommand[theWord]; EXITS dictionaryBlownAway => NULL; }; }; FinalizeDictionaryServer: PUBLIC PROC [] = { permMessage ¬ NIL; }; DefinitionStats: PUBLIC PROC [] RETURNS [totalDefinitions, totalDefinitionsWorked: INT] = { totalDefinitions ¬ totalDefinitionsCnt; totalDefinitionsWorked ¬ totalDefinitionsWorkedCount; }; BruteForceCorrection: PUBLIC PROC [word: ROPE, f: PROC [REF TEXT] RETURNS [BOOL], buffer: REF TEXT] RETURNS [corrections: LIST OF ROPE ¬ NIL, newBuffer: REF TEXT] = { s: CARDINAL ¬ word.Size[]; potentialCorrections: LIST OF ROPE; Test: PROC [w: REF TEXT] = INLINE { IF f[w] THEN corrections ¬ CONS[Rope.FromRefText[w], corrections]; }; potentialCorrections ¬ Dictionary.Corrections[word: word, language: checker]; FOR pc: LIST OF ROPE ¬ potentialCorrections, pc.rest UNTIL pc = NIL DO refText: REF TEXT ¬ Rope.ToRefText[base: pc.first]; Test[refText]; ENDLOOP; }; Define: PROC [word: ROPE] RETURNS [definition: Dictionary.Definition] = { ENABLE { UNWIND => {}; Dictionary.Error => { SELECT problem FROM courier => PutCourierError[permMessage, explanation]; service => PutServiceError[permMessage, explanation]; ENDCASE => ERROR; GOTO Out; }; }; definition ¬ Dictionary.GetDefinition[word: word, dictionary: dictionary]; EXITS Out => RETURN[NIL]; }; Pronunciation: PUBLIC PROC [word: ROPE] RETURNS [wordPronounced: ROPE] = { ENABLE { UNWIND => {}; Dictionary.Error => { SELECT problem FROM courier => PutCourierError[permMessage, explanation]; service => PutServiceError[permMessage, explanation]; ENDCASE => ERROR; GOTO Out; }; }; IF Rope.Length[wordPronounced] =0 THEN wordPronounced ¬ "\n not found "; wordPronounced ¬ Rope.Cat[wordPronounced, "\n", Dictionary.Pronunciation[word: word, dictionary: dictionary]]; EXITS Out => RETURN[NIL]; }; Synonyms: PUBLIC PROC [word: ROPE] RETURNS [listOfSynonyms: ROPE] = { ENABLE { UNWIND => {}; Dictionary.Error => { SELECT problem FROM courier => PutCourierError[permMessage, explanation]; service => PutServiceError[permMessage, explanation]; ENDCASE => ERROR; GOTO Out; }; }; synonymClassesList: Dictionary.SynonymClassesList ¬ Dictionary.Synonyms[word: word, dictionary: dictionary].synonymList; FOR classList: Dictionary.SynonymClassesList ¬ synonymClassesList, classList.rest UNTIL classList = NIL DO FOR wordList: Dictionary.SynonymClassList ¬ classList.first, wordList.rest UNTIL wordList = NIL DO listOfSynonyms ¬ Rope.Cat[listOfSynonyms, " ",wordList.first]; ENDLOOP; listOfSynonyms ¬ Rope.Concat[listOfSynonyms,"\n"]; ENDLOOP; listOfSynonyms ¬ IF Rope.Length[listOfSynonyms] =0 THEN "\n not found " ELSE Rope.Concat["\n",listOfSynonyms]; EXITS Out => RETURN[NIL]; }; WordNerd: PUBLIC PROC [words: ROPE, minKeyWords: INT, minWords: INT, maxWords: INT, nerd: SpellingToolServices.NerdType] RETURNS [listOfNerds: ROPE] = { ENABLE { UNWIND => {}; Dictionary.Error => { SELECT problem FROM courier => PutCourierError[permMessage, explanation]; service => PutServiceError[permMessage, explanation]; ENDCASE => ERROR; GOTO Out; }; }; nerdName: ATOM ¬ IF nerd=EtymologyNerd THEN $EtymologyNerd ELSE $WordNerd; intersectionResultsList: Dictionary.IntersectionResultsList ¬ Dictionary.SearchForWord[unparsedClasses: words, minKeyWords: minKeyWords, minWord: minWords, maxWord: maxWords, dictionary: nerdName]; FOR nerdList: Dictionary.IntersectionResultsList ¬ intersectionResultsList, nerdList.rest UNTIL nerdList = NIL DO FOR keyList: Dictionary.WordsList ¬ nerdList.first.keys, keyList.rest UNTIL keyList = NIL DO listOfNerds ¬ Rope.Cat[listOfNerds, " ",keyList.first]; ENDLOOP; listOfNerds ¬ Rope.Concat[listOfNerds,"\n"]; FOR resultList: Dictionary.WordsList ¬ nerdList.first.results, resultList.rest UNTIL resultList = NIL DO listOfNerds ¬ Rope.Cat[listOfNerds, " ",resultList.first]; ENDLOOP; listOfNerds ¬ Rope.Concat[listOfNerds,"\n\n"]; ENDLOOP; listOfNerds ¬ IF Rope.Length[listOfNerds] =0 THEN "\n not found " ELSE Rope.Concat["\n",listOfNerds]; EXITS Out => RETURN[NIL]; }; SetupLooksTranslator: PRIVATE PROC [] = { looksDefs: AtomListList = Dictionary.GetLooks[dictionary]; RefTab.Erase[looksTranslator]; FOR defs: AtomListList ¬ looksDefs, defs.rest WHILE defs # NIL DO def: AtomList = defs.first; dictLook: ATOM = def.first; cedarLooks: REF TextLooks.Looks = NEW [TextLooks.Looks ¬ TextLooks.noLooks]; FOR pairs: AtomList ¬ def.rest, pairs.rest.rest WHILE pairs # NIL DO attribute: ATOM = pairs.first; value: ATOM = pairs.rest.first; Bitch: PROC = { permMessage.PutFL["Can't cedarize %a=%a on look %a from dictionary %a --- will underline instead\n", LIST[[atom[attribute]], [atom[value]], [atom[dictLook]], [atom[dictionary]]] ]; cedarLooks['z] ¬ TRUE; }; SELECT attribute FROM $FAMILY => SELECT value FROM $TIMESROMAN => NULL; $HELVETICA => cedarLooks['o] ¬ TRUE; $HIPPO => cedarLooks['g] ¬ TRUE; ENDCASE => Bitch[]; $SIZE => { size: INT = Convert.IntFromRope[Atom.GetPName[value]]; SELECT size FROM <10 => cedarLooks['s] ¬ TRUE; =10 => NULL; >12 => cedarLooks['x] ¬ TRUE; ENDCASE => cedarLooks['l] ¬ TRUE; }; $FACE => SELECT value FROM $STANDARD => NULL; $BOLD => cedarLooks['b] ¬ TRUE; $ITALIC => cedarLooks['i] ¬ TRUE; $BOLDITALIC => cedarLooks['b] ¬ cedarLooks['i] ¬ TRUE; ENDCASE => Bitch[]; $SUPERSCRIPT => cedarLooks['u] ¬ TRUE; $SUBSCRIPT => cedarLooks['d] ¬ TRUE; ENDCASE => Bitch[]; ENDLOOP; IF cedarLooks['d] OR cedarLooks['u] THEN cedarLooks['s] ¬ FALSE; IF NOT RefTab.Store[looksTranslator, dictLook, cedarLooks] THEN ERROR; ENDLOOP; }; PutNode: PROC [stream: STREAM, node: Tioga.Node, start: INT ¬ 0, len: INT ¬ INT.LAST] ~ { prevLooks: Tioga.Looks ~ IOTioga.GetLooks[stream]; IF node.runs=NIL THEN { IOTioga.SetLooks[stream, Tioga.noLooks]; IO.PutRope[stream, node.rope, start, len]; } ELSE { index: INT ¬ start; action: Rosary.RunActionType ~ { looks: Tioga.Looks ~ TextEdit.LooksFromItem[item]; IOTioga.SetLooks[stream, looks]; IO.PutRope[stream, node.rope, index, repeat]; index ¬ index+repeat; }; [] ¬ Rosary.MapRuns[[base: node.runs, start: start, size: len], action]; }; IOTioga.SetLooks[stream, prevLooks]; }; PutWithRuns: PRIVATE PROC [to: IO.STREAM, rope: ROPE, dictRuns: Dictionary.RunList] = { node: Tioga.Node ¬ TextEdit.FromRope[rope]; FOR drs: Dictionary.RunList ¬ dictRuns, drs.rest WHILE drs # NIL DO dr: Dictionary.RunPointer = drs.first; cedarLooks: REF TextLooks.Looks ¬ NARROW[RefTab.Fetch[looksTranslator, dr.font].val]; IF dr.length = 0 THEN LOOP; IF cedarLooks = NIL THEN { to.PutF["Got unexpected look %a (from dictionary %a) --- will use underlining\n", [atom[dr.font]], [atom[dictionary]]]; cedarLooks ¬ unexpectedLooks; }; TextEdit.ChangeLooks[root: node, text: node, add: cedarLooks­, start: dr.start + dOrigin, len: dr.length]; ENDLOOP; PutNode[to, node]; }; dOrigin: INT ¬ -1 --add this to dictionary's origin to get Cedar's origin--; unexpectedLooks: REF TextLooks.Looks ¬ NEW [TextLooks.Looks ¬ TextLooks.RopeToLooks["z"]]; PutCourierError: PROC[out: STREAM, exp: ROPE] ~ { IO.PutF1[out, "Unable to connect to dictionary server %g\n", [rope[exp]] ] }; PutServiceError: PROC[out: STREAM, exp: ROPE] ~ { IO.PutF1[out, "The dictionary server is down %g\n", [rope[exp]] ] }; }. l SpellingToolServicesImpl.mesa Copyright Σ 1985, 1987, 1989, 1992 by Xerox Corporation. All rights reserved. Jack Kent August 18, 1987 2:19:05 pm PDT Tim Diebert: August 18, 1989 12:36:08 pm PDT Willie-s, June 1, 1992 10:11 pm PDT ExtractOneWord: PRIVATE PROC [word: REF TEXT] RETURNS [stop: BOOLEAN _ TRUE] = TRUSTED {wordNoBlank _ Rope.FromRefText[word]}; [] _ SpellingToolShared.MapWordsInSelection[s.start, s.end, ExtractOneWord, TRUE, TRUE, TRUE]; Generates all words close to "word" and returns a list of those for which f returns TRUE. The generation of close words proceeds in the usual brute-force manner: transpositions of adjacent letters in the word are considered first, then deletions of single letters, then insertions of single letters from 'a to 'z, and finally replacement of single letters by one of the other twenty five letters between 'a and 'z. The corrections proposed try to mimic the same capitalization style of the root word. Tests to see if a correction is in the word list and adds it to the correction list if it is. for each word in potentialCorrections, put it in corrections if it satisfies f flatten rope Conjugate: PUBLIC PROC [word: ROPE] RETURNS [conjugationsList: Dictionary.ConjugationsList] = { conjugationsList _ Dictionary.Conjugate[word: word, form: $Single, alternates: $Mumble, language: conjug]; }; make words into list of words Κ α•NewlineDelimiter –(cedarcode) style™codešœ™Kšœ ΟeœC™NKšœ(™(K™,K™#K˜šΟk œ˜ Kšœ ˜ K˜K˜ K˜Kšžœ˜K˜Kšœžœ ˜Kšœžœ$˜0K˜K˜K˜Kšœžœ'˜?K˜ K˜ K˜Kšœ žœ˜,Kšœ žœ˜——K˜šΠlnœžœžœ˜(Kšžœ'žœR˜‚Kšžœ˜ K˜Kšžœžœžœžœ˜Kšžœžœžœ˜K˜Kš œ žœžœžœžœ˜Kšœžœžœžœ ˜&K˜K˜Kšœžœžœ˜Kšœ2žœ˜:Kšœ žœžœ˜Kšœ žœ˜%Kšœ žœ˜Kšœžœ˜Kšœžœžœ˜K˜.K˜šΟnœžœžœžœ˜Bšžœ˜Kšžœ˜ ˜šžœ ž˜K˜5K˜5Kšžœžœ˜—KšžœΟc3˜=K˜—Kšœ˜—K˜Kšœ˜K˜—K˜•StartOfExpansion† -- [parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: Menus.MouseButton _ red, shift: BOOL _ FALSE, control: BOOL _ FALSE] -- šΠbnœžœžœ˜3Kšœžœ˜š œž œ žœžœ˜;Kšœžœžœ˜Kšœ"˜"Kšžœžœjžœžœ˜–šžœ$žœ˜,KšœB˜BKšžœ˜K˜>—Kšžœžœ%˜,K˜—šœ˜š’œž œžœ˜9Kšœ~™~Kšœ<˜Kšžœ˜—K˜2Kšžœ˜—šœžœ žœ˜GKšžœ"˜&—Kšžœžœžœ˜K˜K˜—š œžœžœ žœžœ žœ žœ'žœžœ˜˜šžœ˜Kšžœ˜ ˜šžœ ž˜K˜5K˜5Kšžœžœ˜—Kšžœ˜ K˜—Kšœ˜—K™Kš œ žœžœžœžœ ˜JK–"[word: ROPE, dictionary: ATOM]˜ΕšžœWžœ žœžœ˜ršžœCžœ žœžœ˜]K˜7—Kšžœ˜K˜,šžœLžœžœžœ˜iK˜:—Kšžœ˜K˜.—Kšžœ˜Kšœžœžœžœ˜eKšžœžœžœ˜K˜—K˜K˜š œž œ˜)Kšœ:˜:Kšœ˜šžœ+žœžœž˜AKšœ˜Kšœ žœ˜Kšœ žœžœ'˜Lšžœ-žœ žœž˜DKšœ žœ˜Kšœžœ˜š œžœ˜KšœežœK˜΄Kšœ Οzœžœ˜K˜—šžœ ž˜šœ žœž˜Kšœžœ˜KšœΟoœžœ˜$KšœΟgœžœ˜ Kšžœ ˜—˜ Kšœžœ-˜6šžœž˜KšœΟsœžœ˜Kšœžœ˜ KšœΟxœžœ˜KšžœΟlœžœ˜!—K˜—šœ žœž˜Kšœ žœ˜Kšœ£œžœ˜KšœΟiœžœ˜!Kšœ£œͺœžœ˜6Kšžœ ˜—KšœΟuœžœ˜&KšœΟdœžœ˜$Kšžœ ˜—Kšžœ˜—Kšžœ ¬œžœ «œžœ §œžœ˜@Kšžœžœ5žœžœ˜FK˜Kšžœ˜—K˜K˜—š œžœ žœžœ žœžœžœ˜YK˜2šžœ žœžœ˜K˜(Kšžœ(˜*K˜—šžœ˜Kšœžœ ˜˜ K˜2K˜ Kšžœ+˜-K˜K˜—K˜HK˜—K˜$K˜K˜—š   œž œžœžœžœ#˜WK˜+K˜šžœ.žœžœž˜CKšœ&˜&Kšœ žœžœ-˜UKšžœžœžœ˜šžœžœžœ˜Kšœw˜wK˜K˜—KšœQ¦œ˜jKšžœ˜—K˜K˜—K˜Kš¦œžœ‘9œ˜Lšœžœžœ+€œ˜[K˜—š œžœžœžœ˜/KšœžœK˜OK˜—š œžœžœžœ˜/KšœžœB˜FK˜—K˜—K™—…—':O