<<>> <> <> <> <> <> 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; <<[] _ SpellingToolShared.MapWordsInSelection[s.start, s.end, ExtractOneWord, TRUE, TRUE, TRUE];>> 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[' 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 + ENDLOOP; PutNode[to, node]; }; 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]] ] }; }. <<>>