home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Professional / OS2PRO194.ISO / os2 / wps / editor / epmtools / epmmac / epmlex.e < prev    next >
Text File  |  1993-08-04  |  40KB  |  989 lines

  1. /*
  2. ╔════════════════════════════════════════════════════════════════════════════╗
  3. ║ What's it called: EPMLEX.E                                                 ║
  4. ║                                                                            ║
  5. ║ What does it do : Spell checking and Synonym support for the EPM editor.   ║
  6. ║                                                                            ║
  7. ║                   There are two major components to spell and synonym      ║
  8. ║                   checking in EPM.  The first and most important is the    ║
  9. ║                   actual word verification and word/dictionary lookup.     ║
  10. ║                   This is done by the internal EPM opcode, "lexam".        ║
  11. ║                   This opcode can take on the variations indicated by      ║
  12. ║                   the LXF constants defined below.                         ║
  13. ║                                                                            ║
  14. ║                   The second most important part to word checking is the   ║
  15. ║                   presentation of the results.  This is neatly done in     ║
  16. ║                   EPM using a PM list box.  E has an internal list dialog  ║
  17. ║                   accessible through the 'listbox' function.  See          ║
  18. ║                   STDCTRL.E for details on the 'listbox' function.         ║
  19. ║                                                                            ║
  20. ║ Who and When    : Larry Margolis, 11/91                                    ║
  21. ║ Updated from the original                                                  ║
  22. ║ EPMLEX.E done by: C.Maurer,  R.Yozzo,  Gennaro Cuomo, and Larry Margolis   ║
  23. ║                   1/89 - 10/90                                             ║
  24. ╚════════════════════════════════════════════════════════════════════════════╝
  25. */
  26. ; Customizing information:  Any of the following customizing constants can
  27. ; be overridden by including the appropriate definition after a CONST statement
  28. ; in your MYCNF.E.
  29. ;
  30. ; Example of customizing:  include the following lines in your MYCNF.E
  31. ; (with the ';' deleted from the beginning of each line).
  32. ;
  33. ;    const                               -- Customizations for EPMLEX:
  34. ;       RESPECT_case_for_addenda = 0     -- Ignore case of addenda words.
  35. ;       my_ADDENDA_FILENAME= 'd:\doc\margoli.adf'     -- I keep these in my
  36. ;       my_DICTIONARY_FILENAME= 'd:\doc\us.dct'       -- d:\doc directory.
  37. ; Can also have multiple dictionaries, separated by spaces - all will be loaded:
  38. ;       my_DICTIONARY_FILENAME= 'd:\doc\us.dct d:\doc\medical.dct d:\doc\legal.dct'
  39.  
  40. compile if not defined(SMALL)  -- If SMALL not defined, then being separately compiled
  41. include 'stdconst.e'
  42.  define INCLUDING_FILE = 'EPMLEX.E'
  43.    tryinclude 'MYCNF.E'        -- Include the user's configuration customizations.
  44.  compile if not defined(SITE_CONFIG)
  45.     const SITE_CONFIG = 'SITECNF.E'
  46.  compile endif
  47.  compile if SITE_CONFIG
  48.     tryinclude SITE_CONFIG
  49.  compile endif
  50. const
  51.  compile if not defined(SPELL_SUPPORT)  -- Must set here, since set to 0 in ENGLISH.E
  52.    SPELL_SUPPORT = 'DYNALINK'          -- New default
  53.  compile endif
  54.  compile if not defined(NLS_LANGUAGE)
  55.    NLS_LANGUAGE = 'ENGLISH'
  56.  compile endif
  57. include NLS_LANGUAGE'.e'
  58. compile endif
  59.  
  60. const
  61. compile if not defined(PROOF_DIALOG_FIXED)
  62.    PROOF_DIALOG_FIXED = 0               -- 1 if dialog should stay in one spot
  63. compile endif
  64.  
  65. compile if not defined(ADDENDASUPPORT)
  66.    ADDENDASUPPORT =  1                  -- 1 if addenda support
  67. compile endif
  68.  
  69. compile if ADDENDASUPPORT
  70.  compile if not defined(RESPECT_case_for_addenda)
  71. RESPECT_case_for_addenda     = 1        /* If addenda entries are to be     */
  72.  compile endif                          /* placed in the addenda without    */
  73.                                         /* modifying their case, then       */
  74.                                         /* this variable should be 1        */
  75.                                         /* Otherwise, it should be 0        */
  76. compile endif -- ADDENDASUPPORT
  77.  
  78. compile if not defined(PROOF_CIRCLE_STYLE)
  79.    PROOF_CIRCLE_STYLE = 2
  80. compile endif
  81. compile if not defined(PROOF_CIRCLE_COLOR1)
  82.    PROOF_CIRCLE_COLOR1 = 16777220
  83. compile endif
  84. compile if not defined(PROOF_CIRCLE_COLOR2)
  85.    PROOF_CIRCLE_COLOR2 = 16777218
  86. compile endif
  87.  
  88. const
  89. ; Functions
  90. compile if EVERSION >= 5.50     -- Use the new function numbers
  91. LXFINIT   = 0     /* Initialize                   */
  92. LXFTERM   = 1     /* Terminate                    */
  93. LXFGDIC   = 2     /* Pickup Dictionary            */
  94. LXFFDIC   = 3     /* Drop Dictionary              */
  95. LXFSETADD = 4     /* Set Addenda Language Type    */
  96. LXFAD2TRS = 5     /* Add to Transient Addenda     */
  97. LXFREDTRS = 6     /* Read from Transient Addenda  */
  98. LXFSAVTRS = 7     /* Save Transient Addenda       */
  99. LXFVERFY  = 8     /* Verification                 */
  100. LXFSPAID  = 9     /* Spelling Aid                 */
  101. LXFHYPH   =10     /* Hyphenation                  */
  102. LXFDHYPH  =11     /* Dehyphenation                */
  103. LXFSYN    =12     /* Synonym                      */
  104. LXFAMUGDIC=255    /* Addenda Pickup Dictionary    */
  105.          /* (Pseudo-op; calls LXFGDIC internally) */
  106. LXFQLIB   = -1    /* Query Lexam library          */   /* √ */
  107. LXFFINIS  = -2    /* Drop all dicts & terminate   */   /* √ */
  108. LXFPRFLINE= -3    /* Proof an entire line in file */   /*   */
  109. compile else                    -- The old way; uses strings
  110. LXFINIT   = 'I'    -- Initialize
  111. LXFTERM   = 'T'    -- Terminate
  112. LXFGDIC   = 'PI'   -- Pickup Dictionary
  113. LXFFDIC   = 'DR'   -- Drop Dictionary
  114. LXFAD2TRS = 'ADDI' -- Add(ition) to Transient Addenda
  115. LXFVERFY  = 'V'    -- Verification
  116. LXFSPAID  = 'SP'   -- Spelling Aid
  117. LXFSYN    = 'SY'   -- Synonym
  118. LXFAMUGDIC= 'ADDE' -- Addenda Pickup Dictionary
  119. compile endif
  120.  
  121. ; Return codes
  122. LXRFGOOD = 0000   /* Function Successful:  Good Return Code                */
  123. LXRFUPDC = 0005   /* Function Successful:  Updateable dictionary created   */
  124. LXRFNFND = 0100   /* Function Unsuccessful: Word Not Found                 */
  125. LXRFDUPD = 0107   /* Function Unsuccessful: Duplicate Dictionary           */
  126. LXRFINIT = 0200   /* PC LEXAM Not Initialized: Control Block/Parameter Err */
  127. LXRFIFCN = 0201   /* Invalid Function                                      */
  128.  
  129.    LEXAM_PUNCTUATION ='~!@#$¢£¥%^&*()_+|`1234567890-=\{}[]:";''<>?,./¬─═╔╗╚╝┌┐└┘║╦╠╣╩╬┬├┤┴┼│'
  130.  
  131. definit
  132.    universal  addenda_has_been_modified
  133.    universal  ADDENDA_FILENAME
  134.    universal  DICTIONARY_FILENAME
  135.    universal  Dictionary_loaded
  136.  
  137. ; Note:  don't initialize the universals here for EPM if SPELL_SUPPORT =
  138. ; 'DYNALINK'; it will be done in STDCNF so that this won't override the
  139. ; config info read from the .INI file.
  140. compile if EVERSION < 5 or SPELL_SUPPORT <> 'DYNALINK'
  141.  compile if defined(my_ADDENDA_FILENAME)
  142.    ADDENDA_FILENAME= my_ADDENDA_FILENAME
  143.  compile else
  144.    ADDENDA_FILENAME= 'c:\lexam\lexam.adl'
  145.  compile endif
  146.  
  147.  compile if defined(my_DICTIONARY_FILENAME)
  148.    DICTIONARY_FILENAME= my_DICTIONARY_FILENAME
  149.  compile else
  150.    DICTIONARY_FILENAME= 'c:\lexam\us.dct'
  151.  compile endif
  152. compile endif
  153.  
  154.    addenda_has_been_modified=0
  155.    Dictionary_loaded = 0
  156.  
  157. /*
  158. ╔════════════════════════════════════════════════════════════════════════════╗
  159. ║ Synonym Support                                                            ║
  160. ╚════════════════════════════════════════════════════════════════════════════╝
  161. */
  162. /*
  163. ┌────────────────────────────────────────────────────────────────────────────┐
  164. │ What's it called: syn                                                      │
  165. │                                                                            │
  166. │ What does it do : The syn command uses E's lexam support to retrieve       │
  167. │                   possible synonyms for a specified word.                  │
  168. │                   If synonyms are found a                                  │
  169. │                   PM list box is shown containing the possible new words.  │
  170. │                                                                            │
  171. └────────────────────────────────────────────────────────────────────────────┘
  172. */
  173. defc syn =
  174.    if load_lexam() then
  175.      return
  176.    endif
  177.    call pbegin_word()
  178.    call synonym()
  179.    call drop_dictionary()
  180.  
  181.  
  182. /*
  183. ┌────────────────────────────────────────────────────────────────────────────┐
  184. │ What's it called: synonym()                                                │
  185. │                                                                            │
  186. │ What does it do : checks the next word on a line for its possible synonyms.│
  187. │                   possible synonyms for a specified word.                  │
  188. │                   If synonyms are found a                                  │
  189. │                   PM list box is shown containing the possible new words.  │
  190. │                                                                            │
  191. └────────────────────────────────────────────────────────────────────────────┘
  192. */
  193. defproc synonym()
  194.    getline line                           /* get the current line          */
  195. compile if EVERSION >= '5.21'
  196.    line = translate(line, ' ', \9)  -- Convert tabs to spaces
  197. compile endif
  198.    if line<>'' then                       /* if it is NOT blank            */
  199.       i=.col                              /* get the current column number */
  200.       l=pos(' ',line,.col)                /* get possible word             */
  201.       if l=0 then                         /* could this be a word???       */
  202.          l=length(line)+1
  203.          if l<i then l=i endif
  204.       endif
  205.       wrd=strip(substr(line,i,l-i))       /* extract word candidate        */
  206.       oldwordlen=length(wrd)              /* save the length of the word   */
  207.       result=lexam(LXFVERFY,wrd)          /* authenticate word using lexam */
  208.       if result and wrd<>'' then          /* was it a success???             */
  209.          call strippunct(wrd,l,i)
  210.         .col=.col+i-1
  211.          result = lexam(LXFVERFY,wrd)
  212.       endif
  213.       if(result <> LXRFGOOD) then         /* was it a success ???          */
  214.          sayerror NO_MATCH__MSG '<'wrd'>' /* NO                      */
  215.          return ''                        /* exit function                 */
  216.       endif
  217.       /* It's a word!!!     */
  218.                                           /* get list of synonyms using lex*/
  219.       parse value lexam(LXFSYN,wrd) with 2 '/' result
  220.       if result='' then
  221.          sayerror NO_SYN__MSG '<'wrd'>'
  222.          return ''
  223.       endif
  224.  
  225. compile if EVERSION < 5.21  -- The old way
  226.       do forever
  227.          newword = listbox(SYNONYMS__MSG,'/'result,'/'REPLACE__MSG'/'CANCEL__MSG'/'HELP__MSG'/')
  228.          if newword<>3 then leave; endif
  229.          -- help was pressed
  230.          'helpmenu 14002'
  231.          return ''
  232.       enddo
  233. compile else
  234.       parse value listbox(SYNONYMS__MSG,'/'result,'/'REPLACE__MSG'/'CANCEL__MSG'/'HELP__MSG'/',0,0,0,0,
  235.  compile if EVERSION >= 5.60
  236.                           gethwndc(APP_HANDLE) || atoi(1) || atoi(1) || atoi(14002)) with button 2 newword \0
  237.  compile else
  238.                           atoi(1) || atoi(1) || atoi(14002) || gethwndc(APP_HANDLE)) with button 2 newword \0
  239.  compile endif
  240.       if button<>\1 then
  241.          newword = ''
  242.       endif
  243. compile endif -- EVERSION < 5.21
  244.       if newword<>'' then
  245.          getline line                           /* get the current line          */
  246.          replaceline leftstr(line,.col-1)||newword||substr(line,l)
  247.          return length(newword)-oldwordlen
  248.       endif
  249.    endif
  250.  
  251. /*
  252. ╔════════════════════════════════════════════════════════════════════════════╗
  253. ║ Spell Checking Support                                                     ║
  254. ╚════════════════════════════════════════════════════════════════════════════╝
  255. */
  256.  
  257. /*
  258. ┌────────────────────────────────────────────────────────────────────────────┐
  259. │ What's it called: proof()                                                  │
  260. │                                                                            │
  261. │ What does it do : The proof command uses E's lexam support to spell check  │
  262. │                   either the next word or a given word.     If a misspelled│
  263. │                   word is encountered, a                                   │
  264. │                   PM list box is shown containing the possible corrections.│
  265. │                   syntax:   proof  [word]                                  │
  266. │                          - if 'word' is not specified, proof searchs for   │
  267. │                            the next word (after the cursor) and checks it. │
  268. └────────────────────────────────────────────────────────────────────────────┘
  269. */
  270. defc proof
  271.    universal ADDENDA_FILENAME
  272.    if load_lexam() then
  273.      return
  274.    endif
  275.    if arg(1)<>'' then
  276.       call proof1(arg(1))
  277.    else
  278.       call proof2()
  279.    endif
  280. compile if ADDENDASUPPORT
  281.    if addenda_filename<>'' then
  282.       call maybe_save_addenda()
  283.    endif
  284. compile endif
  285.    call drop_dictionary()
  286.    if arg(1)='' then
  287.       sayerror DONE__MSG
  288.    endif
  289.  
  290. /*
  291. ┌────────────────────────────────────────────────────────────────────────────┐
  292. │ What's it called: proof2()                                                 │
  293. │                                                                            │
  294. │ What does it do : Start at the current cursor position,  locate the next   │
  295. │                   word, and check the spelling of that word.   The spelling│
  296. │                   of each word is done by calling the lexam function.      │
  297. │                   The 'lexam' fuction is a internal                        │
  298. │                   opcode that uses the dynalink feature to access the      │
  299. │                   LEXAM.DLL                                                │
  300. │                                                                            │
  301. └────────────────────────────────────────────────────────────────────────────┘
  302. */
  303. defproc proof2
  304.    script_file_type=AMU_script_verification()
  305.    tex_file_type = (filetype() = 'TEX')
  306.  
  307.  --@@ If there's a line-marked area in the current file, proof only in there.
  308.  firstline=max(.line,1); lastline=.last; what = 'file'
  309.  if marktype() then  /* if no mark, default to entire file */
  310.     getfileid curfileid
  311.     getmark fl,ll,fc,lc,markfileid
  312.     if markfileid = curfileid then
  313.        firstline=fl; lastline=ll
  314.        what = 'marked area'
  315.     endif
  316.  endif
  317.  partial_lines = marktype()='BLOCK' | marktype()='CHAR'
  318.  
  319.  /* start checking at next word...*/
  320. ;getline line
  321. ;.col=1
  322. ;if leftstr(line,1)==' 'then
  323. ;   tabword
  324. ;endif
  325.  if partial_lines then .col=fc; else .col=1; endif
  326.  firstline
  327.  
  328.  for zz= firstline to lastline --@@
  329.    zz                                 /* advance to next (new) line         */
  330.    getline line
  331. compile if EVERSION >= '5.21'
  332.    line = translate(line, ' ', \9)  -- Convert tabs to spaces
  333. compile endif
  334. compile if EVERSION >= '5.21'
  335.    display -8
  336. compile endif
  337. ;  sayerror 'Spell Checking 'what'...'
  338.    sayerror 'Spell Checking 'what '(line' zz'; last='lastline')...'
  339. compile if EVERSION >= '5.21'
  340.    display 8
  341. compile endif
  342.  
  343.    loop
  344.  
  345.      if substr(line, .col, 1)=' ' & substr(line, .col)<>' ' then
  346.         tabword
  347.      endif
  348.      if partial_lines then
  349.         if .col>lc & (zz=lastline | marktype()='BLOCK') then
  350.            if marktype()='BLOCK' then .col=fc; endif
  351.            leave
  352.         endif
  353.      endif
  354.      l=pos(' ',line,.col)                /* find first word                 */
  355.      if not l then                       /* no more words on this line...   */
  356.         l=length(line)+1                 /* or there is only one word on    */
  357.         if l<=.col then                  /* the line...                     */
  358.            if marktype()='BLOCK' then .col=fc; else .col=1; endif
  359.            leave
  360.         endif
  361.      endif
  362.      wrd=substr(line,.col,l-.col)        /* extract word from line          */
  363.      if not verify(wrd, LEXAM_PUNCTUATION) then  -- No letters in "word"; skip it.
  364.         result = 0
  365.      else
  366.         result = lexam(LXFVERFY,wrd)        /* verify word using lexam         */
  367.      endif
  368.      if result and wrd<>'' then          /* was it a success???             */
  369.                                          /* YES, ignore script tags         */
  370.         if script_file_type then  -- Do just the cheap test first.
  371.            if (pos(leftstr(wrd,1),':&.') or pos(substr(line,max(.col-1,1),1),':&')) then
  372.               result=0
  373.               if leftstr(wrd,1)=':' then
  374.                  newl=pos('.',line,.col)
  375.                  if newl then
  376.                     l=newl
  377.                  endif
  378.               endif
  379.            endif
  380.         elseif tex_file_type & leftstr(wrd,1)='\' then
  381.            result=0
  382.         endif
  383.         if result then                 /* strip punctuation and try again */
  384.            call strippunct(wrd,l,i)
  385.           .col=.col+i-1
  386.            result = lexam(LXFVERFY,wrd)
  387.         endif
  388.      endif
  389.      if result and wrd<>'' then
  390. ;;      result = lexam(LXFVERFY,wrd)  -- Redundant???
  391. ;;      if result and wrd<>'' then
  392. compile if EVERSION < 5.21  -- Help is now handled by the dialog box
  393.            -- t=-3 means help was requested, so call spellword again.
  394.            t=-3
  395.            do while t=-3
  396. compile endif
  397. compile if ADDENDASUPPORT
  398.               t=spellword2(wrd, l, '/~Next/~Temp. Add')    -- spell check the word
  399. compile else
  400.               t=spellword2(wrd, l, '/~Next')               -- spell check the word
  401. compile endif
  402. compile if EVERSION < 5.21  -- Help is now handled by the dialog box
  403.            enddo
  404. compile endif
  405.            if t=0 then                         -- error occured
  406.               return 0
  407.            endif
  408.            if t>0 then
  409.               l=l + t - 100
  410.            elseif t=-4 then   -- Edit was selected.
  411.               l = .col -1     -- (so .col won't change; recheck from current point)
  412.            endif
  413.            getline line
  414. compile if EVERSION >= '5.21'
  415.            line = translate(line, ' ', \9)  -- Convert tabs to spaces
  416. compile endif
  417. ;;      endif
  418.      endif
  419.      .col=l+1
  420.    endloop
  421.  endfor
  422.  
  423. compile if PROOF_DIALOG_FIXED
  424.    define DIALOG_POSN = ', -2, .windowwidth'
  425. compile elseif EVERSION < 5.21
  426.    define DIALOG_POSN = ' '
  427. compile else
  428.    define DIALOG_POSN = ', 0, 0 '
  429. compile endif
  430. /*
  431. ┌────────────────────────────────────────────────────────────────────────────┐
  432. │ What's it called: spellword()                                              │
  433. │                                                                            │
  434. │ What does it do : Check the word at the cursor position, removing          │
  435. │                   punctuation characters.  It is assumed that the cursor   │
  436. │                   is positioned at the beginning of the word.  (Used by    │
  437. │                   proof2 and proofword.)  If it's a valid word then check  │
  438. │                   the spelling of the word using the lexam opcode.  If a   │
  439. │                   valid result is returned place it in a PM list box using │
  440. │                   the 'listbox' procedure.  Returns the length of the word │
  441. │                   found.  The optional argument is a string containing a   │
  442. │                   button name.  E.g., '/Next'                              │
  443. └────────────────────────────────────────────────────────────────────────────┘
  444. */
  445. defproc spellword
  446.    getline line                              /* ignore script tags           */
  447. compile if EVERSION >= '5.21'
  448.    line = translate(line, ' ', \9)  -- Convert tabs to spaces
  449. compile endif
  450.    if line<>'' then                          /* if the line is not empty...  */
  451.       i=.col                                 /* save the cursor column       */
  452.       l=pos(' ',line,.col)                   /* get next word after cursor   */
  453.       if l=0 then                            /* is it a word???              */
  454.          l=max(length(line)+1, i)
  455.       endif
  456.       wrd=strip(substr(line,i,l-i))          /* extract word from line       */
  457.       result = lexam(LXFVERFY,wrd)           /* verify word                  */
  458.       if result and wrd<>'' then             /* was it a success             */
  459.          start_l = l
  460.          do forever
  461.             call strippunct(wrd,l,i)            /* strip punctuation/ try again */
  462.             .col=.col+i-1                       /* move to next column          */
  463.             if l>=arg(2) | wrd='' then  -- Will always be true if arg(2) omitted.
  464.                leave
  465.             endif
  466.             .col = l
  467.             l = start_l
  468.             wrd=strip(substr(line,.col,l-.col))    /* extract word from line       */
  469.          enddo
  470.          result = lexam(LXFVERFY,wrd)        /* try word  verification again */
  471.       endif
  472.       if (result or abbrev('FORCE', upcase(arg(3)), 1)) and wrd<>'' then             /* was it a success             */
  473.           return spellword2(wrd, l, arg(1))
  474.       else
  475.          --.messageline='word is spelled correctly'
  476.          return -2
  477.       endif
  478.    endif
  479.    return 0
  480.  
  481. defproc spellword2(wrd, l)
  482.          oldwordlen=length(wrd)              /* yes it's a word.....         */
  483.                                              /* use lexam to spell check word*/
  484.          refresh
  485.          parse value lexam(LXFSPAID,wrd) with 2 '/' result
  486.          if rc>=LXRFINIT then
  487.             sayerror LOOKUP_FAILED__MSG '<' wrd '> RC='rc
  488.             return -1  -- next word
  489.          else
  490.             if result='' then
  491.                result='*Nothing Found*'
  492.             endif
  493.             oldcol = .col; .col = .col + oldwordlen; .col = oldcol;
  494. compile if EVERSION < '5.50'
  495.             refresh
  496.             sayat wrd, .cursory, .cursorx,
  497.                   .textcolor%16+(.textcolor // 16)*16, oldwordlen
  498. compile elseif EVERSION >= 5.60
  499.             circleit PROOF_CIRCLE_STYLE, .line, .col, .col+oldwordlen-1, PROOF_CIRCLE_COLOR1, PROOF_CIRCLE_COLOR2
  500.             refresh  -- Refresh required to display circle, because control isn't being returned to the user
  501. compile else
  502.             circleit PROOF_CIRCLE_STYLE, .line, .col, .col+oldwordlen-1, 1 -- color irrelevant now
  503.             refresh  -- Refresh required to display circle, because control isn't being returned to the user
  504. compile endif
  505. compile if ADDENDASUPPORT
  506.  compile if EVERSION < 5.21  -- The old way
  507.             newword=listbox(PROOF__MSG '<'wrd'>', '/'result,
  508.                             '/'REPLACE__MSG'/'CANCEL__MSG||arg(3)'/'ADD__MSG'/'EDIT__MSG'.../'HELP__MSG $DIALOG_POSN)   -- put result in PM list box
  509.  compile else
  510.             parse value listbox(PROOF__MSG '<'wrd'>', '/'result,
  511.                                 '/'REPLACE__MSG'/'CANCEL__MSG||arg(3)'/'ADD__MSG'/'EDIT__MSG'.../'HELP__MSG $DIALOG_POSN ,0,0,
  512.   compile if EVERSION >= 5.60
  513.                                 gethwndc(APP_HANDLE) || atoi(1) || atoi(1) || atoi(14000)) with button 2 newword \0
  514.   compile else
  515.                                 atoi(1) || atoi(1) || atoi(14000) || gethwndc(APP_HANDLE)) with button 2 newword \0
  516.   compile endif
  517.             if button=\0 | button=\2 then  -- Close or Cancel
  518.                newword = ''
  519.             endif
  520.  compile endif -- EVERSION < 5.21
  521.             if arg(3)='' then
  522.                butlist='7 7 3 4 5'  -- Next; Temp. Add; Add; Edit; Help
  523.             else
  524.                butlist='3 4 5 6 7'  -- Next; Temp. Add; Add; Edit; Help
  525.             endif
  526. compile else
  527.  compile if EVERSION < 5.21  -- The old way
  528.             newword=listbox(PROOF__MSG '<'wrd'>','/'result,'/'REPLACE__MSG'/'CANCEL__MSG ||arg(3)'/'EDIT__MSG'.../'HELP__MSG $DIALOG_POSN)  -- put result in PM list box
  529.  compile else
  530.             parse value listbox(PROOF__MSG '<'wrd'>', '/'result,
  531.                                 '/'REPLACE__MSG'/'CANCEL__MSG||arg(3)'/'EDIT__MSG'.../'HELP__MSG $DIALOG_POSN ,0,0,
  532.   compile if EVERSION >= 5.60
  533.                                 gethwndc(APP_HANDLE) || atoi(1) || atoi(1) || atoi(14000)) with button 2 newword \0
  534.   compile else
  535.                                 atoi(1) || atoi(1) || atoi(14000) || gethwndc(APP_HANDLE)) with button 2 newword \0
  536.   compile endif
  537.             if button=\0 | button=\2 then  -- Close or Cancel
  538.                newword = ''
  539.             endif
  540.  compile endif -- EVERSION < 5.21
  541.             if arg(3)='' then
  542.                butlist='7 7 7 3 4'  -- Next; Temp. Add; Add; Edit; Help
  543.             else
  544.                butlist='3 7 7 4 5'  -- Next; Temp. Add; Add; Edit; Help
  545.             endif
  546. compile endif
  547.             parse value butlist with but_next but_temp_add but_add but_edit but_help
  548. compile if EVERSION < 5.21  -- Help is now handled by the dialog box
  549.             if newword=but_help then
  550.                'helpmenu 14000'
  551.                return -3     -- do line over again
  552.             endif
  553.             if newword=but_edit then
  554. compile else
  555.             if button=chr(but_edit) then
  556. compile endif
  557.                newword=entrybox(REPLACEMENT__MSG '<'wrd'>','/'REPLACE__MSG'/'CANCEL__MSG,wrd)
  558.                if newword='' then
  559.                   return -1  -- next word
  560.                endif
  561.                getline line
  562.                replaceline leftstr(line,.col-1)||newword||substr(line,l)
  563.                refresh
  564. ;;             return -100 - (length(newword)-oldwordlen)    -- Don't care about new len.
  565.                return -4    -- re-check line
  566.             endif
  567. compile if EVERSION < '5.50'
  568.             sayat wrd, .cursory, .cursorx, .textcolor, oldwordlen
  569. compile else
  570. ;           refresh  -- maybe can leave out...
  571. compile endif
  572. compile if EVERSION < 5.21
  573.             if newword=but_next then   -- goto next word
  574. compile else
  575.             if button=chr(but_next) then   -- goto next word
  576. compile endif
  577.                return -1
  578.             endif
  579. compile if ADDENDASUPPORT
  580.  compile if EVERSION < 5.21
  581.             if newword=but_temp_add then   -- temporary addenda (just for this PROOF session)
  582.  compile else
  583.             if button=chr(but_temp_add) then   -- goto next word
  584.  compile endif
  585.  compile if RESPECT_CASE_FOR_ADDENDA
  586.                call lexam(LXFAD2TRS, wrd)
  587.  compile else
  588.                call lexam(LXFAD2TRS,lowcase(wrd))
  589.  compile endif
  590.                return -1
  591.             endif
  592.  compile if EVERSION < 5.21
  593.             if newword=but_add then   -- addenda
  594.  compile else
  595.             if button=chr(but_add) then   -- goto next word
  596.  compile endif
  597.                call AMU_addenda_addition_processing(wrd)
  598.                return -1
  599.             endif
  600. compile endif
  601.             if newword='*Nothing Found*' then
  602.                return -1
  603.             endif
  604.             if newword<>'' then              /* was it a valid result ???    */
  605.                                              /* replace word in line         */
  606.                getline line
  607.                replaceline leftstr(line,.col-1)||newword||substr(line,l)
  608. compile if EVERSION < 5.50
  609.                refresh
  610. compile endif
  611.                return 100 + length(newword)-oldwordlen
  612. ;              return -1
  613.             endif
  614.           endif
  615.    return 0
  616.  
  617. /*
  618. ┌────────────────────────────────────────────────────────────────────────────┐
  619. │ What's it called: proof1()                                                 │
  620. │                                                                            │
  621. │ What does it do : Takes a word argument and looks it up in the lexam       │
  622. │                   dictionary using the 'lexam' opcode.                     │
  623. │                   If the word is found a list box is presented with the    │
  624. │                   possible correct word choices.                           │
  625. └────────────────────────────────────────────────────────────────────────────┘
  626. */
  627. defproc proof1( wrd )
  628.    result = lexam(LXFVERFY,wrd)            /* first off, is it a word?    */
  629.    if result then                          /* well is it???               */
  630.       result = lexam(LXFSPAID,wrd)         /* YES, now check it with lexam*/
  631.  
  632.       parse value result with .'/' result  /* remove first word           */
  633.       if rc>=LXRFINIT then
  634.          sayerror LOOKUP_FAILED__MSG '<' wrd '>'
  635.       else
  636.          if result='' then
  637.             result='*Nothing Found*'
  638.          endif
  639. compile if EVERSION < 5.21  -- The old way
  640.          do forever
  641.  compile if ADDENDASUPPORT
  642.             newword=listbox(PROOF_WORD__MSG,'/'result,'/'REPLACE__MSG'/'EXIT__MSG'/'ADD__MSG'/'HELP__MSG)     /* put result in PM list box   */
  643.             if newword='3' then   --  addenda
  644.                call AMU_addenda_addition_processing(wrd)
  645.                return -1
  646.             endif
  647.             if newword<>4 then leave; endif
  648.  compile else
  649.             newword=listbox(PROOF_WORD__MSG,'/'strip(result),'/'REPLACE__MSG'/'EXIT__MSG'/'HELP__MSG)     /* put result in PM list box   */
  650.             if newword<>3 then leave; endif
  651.  compile endif
  652.             'helpmenu 14001'
  653.          enddo
  654. compile else
  655.          parse value listbox(PROOF_WORD__MSG, '/'result,
  656.  compile if ADDENDASUPPORT
  657.                              '/'REPLACE__MSG'/'EXIT__MSG'/'ADD__MSG'/'HELP__MSG,
  658.  compile else
  659.                              '/'REPLACE__MSG'/'EXIT__MSG'/'HELP__MSG
  660.  compile endif
  661.  compile if EVERSION >= 5.60
  662.                              gethwndc(APP_HANDLE) || atoi(1) || atoi(1) || atoi(14001)) with button 2 newword \0
  663.  compile else
  664.                              atoi(1) || atoi(1) || atoi(14001) || gethwndc(APP_HANDLE)) with button 2 newword \0
  665.  compile endif
  666.          if button=\0 | button=\2 then  -- Close or Cancel
  667.             newword = ''
  668.  compile if ADDENDASUPPORT
  669.          elseif button=\3 then   --  addenda
  670.             call AMU_addenda_addition_processing(wrd)
  671.             return -1
  672.  compile endif
  673.          endif
  674. compile endif -- EVERSION < 5.21
  675.          if newword='*Nothing Found*' then
  676.             return
  677.          endif
  678.          return newword
  679.       endif
  680.    endif
  681.  
  682. /*
  683. ╔════════════════════════════════════════════════════════════════════════════╗
  684. ║ Addenda Support                                                            ║
  685. ╚════════════════════════════════════════════════════════════════════════════╝
  686. */
  687. compile if ADDENDASUPPORT
  688. /*
  689. ┌────────────────────────────────────────────────────────────────────────────┐
  690. │ What's it called: maybe_save_addenda                                       │
  691. │                                                                            │
  692. │ What does it do :                                                          │
  693. │                                                                            │
  694. └────────────────────────────────────────────────────────────────────────────┘
  695. */
  696. ; Addenda support commands
  697.  
  698. defproc maybe_save_addenda
  699.    universal  addenda_has_been_modified
  700.    universal  AMU_addenda_file_identification
  701.    universal  ADDENDA_FILENAME
  702.  
  703. ;   if addenda_has_been_modified then
  704.      -- sayatbox 'saving addenda 'ADDENDA_FILENAME
  705.       if AMU_addenda_file_identification<>''  then
  706.        getfileid AMU_current_file_identification
  707.        rc = 0
  708.        activatefile AMU_addenda_file_identification
  709.        if not rc then
  710.           if .modify then 'xcom save'; endif
  711. ;;        'xcom quit'
  712.        endif
  713.        -- sayerror 'addenda file filed'
  714.        activatefile AMU_current_file_identification
  715.       endif
  716.       addenda_has_been_modified=0
  717.       -- sayerror 0
  718. ;  endif
  719.  
  720. ;defc AMU_addenda_pickup
  721. ;   universal  ADDENDA_FILENAME
  722. ;   call lexam(LXFAMUGDIC,ADDENDA_FILENAME)
  723.  
  724. ;defc AMU_addenda_addition
  725. ;   call lexam(LXFAD2TRS,arg(1))
  726.  
  727. defproc AMU_addenda_processing
  728.    universal AMU_addenda_file_identification
  729.    universal  ADDENDA_FILENAME
  730.    getfileid AMU_current_file_identification
  731.    'xcom e' ADDENDA_FILENAME
  732.    -- sayerror 'addenda file loaded'
  733.    if not rc or rc = sayerror('New file') then
  734.       getfileid AMU_addenda_file_identification
  735.    else
  736.       AMU_addenda_file_identification =''
  737.       sayerror BAD_ADDENDA__MSG ADDENDA_FILENAME 'rc=' rc
  738.       stop
  739.    endif
  740.    .visible=0 -- hidden file
  741.    activatefile AMU_current_file_identification
  742.    if AMU_addenda_file_identification <>'' then
  743.       for i = 1 to AMU_addenda_file_identification.last
  744.          getline line,i,AMU_addenda_file_identification
  745.          if upcase(leftstr(line, 8))='.DU ADD ' then
  746.             line=substr(line,9)
  747.          endif
  748.          do while line <> ''
  749.             parse value line with wrd line
  750.  compile if RESPECT_CASE_FOR_ADDENDA
  751.             call lexam(LXFAD2TRS,wrd)
  752.  compile else
  753.             call lexam(LXFAD2TRS,lowcase(wrd))
  754.  compile endif
  755.          enddo
  756.       endfor
  757.    endif
  758.  
  759. defproc AMU_addenda_addition_processing(AMU_addenda_entry)
  760.    universal  addenda_has_been_modified
  761.    universal AMU_addenda_file_identification, ADDENDA_FILENAME
  762.    addenda_has_been_modified=1
  763.  compile if not RESPECT_CASE_FOR_ADDENDA
  764.    AMU_addenda_entry=lowcase(AMU_addenda_entry)
  765.  compile endif
  766.    call lexam(LXFAD2TRS,AMU_addenda_entry)
  767.    if ADDENDA_FILENAME<>'' & AMU_addenda_file_identification<>'' then
  768.       insertline AMU_addenda_entry,AMU_addenda_file_identification.last+1,AMU_addenda_file_identification
  769.    endif
  770.  
  771.  
  772. compile endif -- ADDENDASUPPORT
  773.  
  774. ; The following is a script file type verification algorithm
  775. ; suggested by Larry Margolis. (Thanks, Larry)
  776. defproc AMU_script_verification()
  777.    ext=filetype()
  778. compile if defined(my_SCRIPT_FILE_TYPE)
  779.    return ext='SCR' or ext='SCT' or ext='SCRIPT' or ext='IPF' or ext=my_SCRIPT_FILE_TYPE
  780. compile else
  781.    return ext='SCR' or ext='SCT' or ext='SCRIPT' or ext='IPF'
  782. compile endif
  783.  
  784.  
  785. /*
  786. ╔════════════════════════════════════════════════════════════════════════════╗
  787. ║ General Lexam Support                                                      ║
  788. ╚════════════════════════════════════════════════════════════════════════════╝
  789. */
  790. defproc load_lexam
  791.    universal DICTIONARY_FILENAME
  792.    universal ADDENDA_FILENAME
  793.    universal Dictionary_loaded
  794.    rc = 0
  795.    result = lexam(LXFINIT)
  796.    if (result<>LXRFGOOD and result<>LXRFIFCN) or rc=-322 then
  797.       if result='febe' or rc=-322 then  -- x'febe' = -322 = sayerror('Dynalink: unrecognized library name')
  798. compile if EVERSION < '5.60a'  -- 5.60a and above give the message internally
  799.          sayerror sayerrortext(-322) LEXAM_DLL'.DLL'
  800. compile endif
  801.       else
  802.          sayerror INIT_ERROR__MSG '('rc')'
  803.       endif
  804.       return 1
  805.    endif
  806.    dictlist=DICTIONARY_FILENAME
  807.    do while dictlist <> ''
  808.       parse value dictlist with dictionary dictlist
  809.       result=lexam(LXFGDIC, dictionary)
  810.       if result>=LXRFNFND & result<>LXRFDUPD then  -- Duplicate Dictionary; didn't unload?
  811.          if exist(dictionary) then
  812.             sayerror BAD_DICT__MSG '"'dictionary'";' ERROR__MSG result
  813.          else
  814.             sayerror NO_DICT__MSG '"'dictionary'"'
  815.          endif
  816.          return 1
  817.       endif
  818.    enddo
  819.    Dictionary_loaded = 1
  820. compile if ADDENDASUPPORT
  821.    if ADDENDA_FILENAME<>'' then
  822.       result = lexam(LXFAMUGDIC,ADDENDA_FILENAME)
  823.       if result & result<>LXRFUPDC then
  824.          sayerror BAD_ADDENDA__MSG '"'ADDENDA_FILENAME'";' ERROR__MSG result
  825.       else
  826.          call AMU_addenda_processing()
  827.       endif
  828.    endif
  829. compile endif
  830.    return 0
  831.  
  832. defproc drop_dictionary
  833.    universal DICTIONARY_FILENAME
  834.    universal  ADDENDA_FILENAME
  835.    universal  Dictionary_loaded
  836.    dictlist=DICTIONARY_FILENAME
  837.    do while dictlist <> ''
  838.       parse value dictlist with dictionary dictlist
  839.       call lexam(LXFFDIC, dictionary);
  840.    enddo
  841. compile if ADDENDASUPPORT
  842.    if ADDENDA_FILENAME<>'' then
  843.       call lexam(LXFFDIC,ADDENDA_FILENAME);
  844.    endif
  845. compile endif
  846.    call lexam(LXFTERM)
  847.    Dictionary_loaded = 0
  848.  
  849. defproc strippunct(var wrd,var l,var i)
  850.    /* strip leading and trailing punctuation and try again*/
  851.    i=verify(wrd, LEXAM_PUNCTUATION)
  852.    if i then
  853.       j = length(wrd)
  854.       do while pos(substr(wrd, j, 1), '.?!,:;')  -- Extra check, to accept "didn't."
  855.          j = j - 1
  856.       enddo
  857.       if j<length(wrd) then
  858.          if not lexam(LXFVERFY, leftstr(wrd, j)) then  -- If result is 0, word is good.
  859.             i = 1
  860. ;;          l = l - length(wrd) + j
  861.             wrd = leftstr(wrd, j)
  862.             return
  863.          endif
  864.       endif
  865.       l=l-length(wrd)
  866.       wrd=substr(wrd,i)
  867.       j=verify(wrd, LEXAM_PUNCTUATION,'m')
  868.       if j then
  869.          wrd=leftstr(wrd,j-1)
  870.       else
  871.          j=length(wrd)+1
  872.       endif
  873.       l=l+j+i-2
  874.    else
  875.       i=length(wrd)+1
  876.    endif
  877.  
  878. defc proofword,verify
  879.    universal ADDENDA_FILENAME
  880.    if load_lexam() then
  881.      return
  882.    endif
  883.    orig_col = .col
  884.    call pbegin_word()
  885.    if substr(textline(.line), orig_col, 1)=' ' & .col < orig_col then
  886.       tmp = .col
  887.       call pend_word()
  888.       orig_col = .col
  889.       .col = tmp
  890.    endif
  891.    spellrc = spellword('', orig_col, arg(1))
  892. compile if ADDENDASUPPORT
  893.    if addenda_filename<>'' then
  894.       call maybe_save_addenda()
  895.    endif
  896. compile endif
  897.    call drop_dictionary()
  898.    if -2 = spellrc then
  899.       sayerror SPELLED_OK__MSG
  900.    endif
  901.  
  902. defc dict
  903.    universal DICTIONARY_FILENAME
  904.    dictlist = arg(1)
  905.    if dictlist='' then
  906.       sayerror DICTLIST_IS__MSG DICTIONARY_FILENAME
  907.       return
  908.    endif
  909.    do while dictlist <> ''
  910.       parse value dictlist with dictionary dictlist
  911.       if not exist(dictionary) then
  912.          sayerror FILE_NOT_FOUND__MSG '"'dictionary'"; 'DICT_REMAINS__MSG DICTIONARY_FILENAME
  913.          return
  914.       endif
  915.    enddo
  916.    DICTIONARY_FILENAME = arg(1)
  917.  
  918. compile if EVERSION >= 5.60
  919. defc newproof
  920.    universal ADDENDA_FILENAME
  921.    if load_lexam() then
  922.      return
  923.    endif
  924.    script_file_type=AMU_script_verification()
  925.    tex_file_type = (filetype() = 'TEX')
  926.  
  927.  --@@ If there's a line-marked area in the current file, proof only in there.
  928.    firstline=max(.line,1); lastline=.last; what = 'file'
  929.    if marktype() then  /* if no mark, default to entire file */
  930.       getfileid curfileid
  931.       getmark fl,ll,fc,lc,markfileid
  932.       if markfileid = curfileid then
  933.          firstline=fl; lastline=ll
  934.          what = 'marked area'
  935.       endif
  936.    endif
  937.    partial_lines = marktype()='BLOCK' | marktype()='CHAR'
  938.  
  939.    if partial_lines then .col=fc; else .col=1; endif
  940.    firstline
  941.  
  942.    for zz= firstline to lastline --@@
  943.       zz                                 /* advance to next (new) line         */
  944.  compile if EVERSION >= '5.21'
  945.       display -8
  946.  compile endif
  947. ;     sayerror 'Spell Checking 'what'...'
  948.       sayerror 'Spell Checking 'what '(line' zz'; last='lastline')...'
  949.  compile if EVERSION >= '5.21'
  950.       display 8
  951.  compile endif
  952.       result = lexam(LXFPRFLINE, zz)
  953.       if length(result) then
  954.          offst = 0
  955.          oldlen = length(textline(zz))
  956.          do i = 1 to length(result) by 2
  957.             .col = itoa(substr(result, i, 2), 10) + offst
  958.  compile if ADDENDASUPPORT
  959.             t=spellword('/~Next/~Temp. Add')    -- spell check the word
  960.  compile else
  961.             t=spellword('/~Next')               -- spell check the word
  962.  compile endif
  963.             if t=0 then                         -- error occured
  964.                return 0
  965.             endif
  966.             if t>0 then
  967.                offst = offst + t - 100
  968.             elseif t=-4 then   -- Edit was selected.
  969.                i = i - 2  -- Repeat at this position.  (???)
  970.                newlen = length(textline(zz))
  971.                offst = offst + newlen - oldlen
  972.                oldlen = newlen
  973.             endif
  974.          enddo
  975.       endif
  976.    endfor
  977.  
  978.  compile if ADDENDASUPPORT
  979.    if addenda_filename<>'' then
  980.       call maybe_save_addenda()
  981.    endif
  982.  compile endif
  983.    call drop_dictionary()
  984.    if arg(1)='' then
  985.       sayerror DONE__MSG
  986.    endif
  987.  
  988. compile endif  -- >= 5.60
  989.