home *** CD-ROM | disk | FTP | other *** search
/ The Developer Connection…ice Driver Kit for OS/2 3 / DEV3-D1.ISO / editors / epm / sampmacs / epmlex.e < prev    next >
Encoding:
Text File  |  1993-12-09  |  59.1 KB  |  1,504 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. compile if (EVERSION >= '5.60c' & EVERSION < 6) | EVERSION >= '6.00c'
  132.    USE_CUSTOM_PROOF_DIALOG = 1
  133. compile else
  134.    USE_CUSTOM_PROOF_DIALOG = 0
  135. compile endif
  136.  
  137. definit
  138.    universal  addenda_has_been_modified
  139.    universal  ADDENDA_FILENAME
  140.    universal  DICTIONARY_FILENAME
  141.    universal  Dictionary_loaded
  142.  
  143. ; Note:  don't initialize the universals here for EPM if SPELL_SUPPORT =
  144. ; 'DYNALINK'; it will be done in STDCNF so that this won't override the
  145. ; config info read from the .INI file.
  146. compile if EVERSION < 5 or SPELL_SUPPORT <> 'DYNALINK'
  147.  compile if defined(my_ADDENDA_FILENAME)
  148.    ADDENDA_FILENAME= my_ADDENDA_FILENAME
  149.  compile else
  150.    ADDENDA_FILENAME= 'c:\lexam\lexam.adl'
  151.  compile endif
  152.  
  153.  compile if defined(my_DICTIONARY_FILENAME)
  154.    DICTIONARY_FILENAME= my_DICTIONARY_FILENAME
  155.  compile else
  156.    DICTIONARY_FILENAME= 'us.dct'
  157.  compile endif
  158. compile endif
  159.  
  160.    addenda_has_been_modified=0
  161.    Dictionary_loaded = 0
  162.  
  163. /*
  164. ╔════════════════════════════════════════════════════════════════════════════╗
  165. ║ Synonym Support                                                            ║
  166. ╚════════════════════════════════════════════════════════════════════════════╝
  167. */
  168. /*
  169. ┌────────────────────────────────────────────────────────────────────────────┐
  170. │ What's it called: syn                                                      │
  171. │                                                                            │
  172. │ What does it do : The syn command uses E's lexam support to retrieve       │
  173. │                   possible synonyms for a specified word.                  │
  174. │                   If synonyms are found a                                  │
  175. │                   PM list box is shown containing the possible new words.  │
  176. │                                                                            │
  177. └────────────────────────────────────────────────────────────────────────────┘
  178. */
  179. defc syn =
  180.    if load_lexam() then
  181.      return
  182.    endif
  183.    call pbegin_word()
  184.    call synonym()
  185.    call drop_dictionary()
  186.  
  187.  
  188. /*
  189. ┌────────────────────────────────────────────────────────────────────────────┐
  190. │ What's it called: synonym()                                                │
  191. │                                                                            │
  192. │ What does it do : checks the next word on a line for its possible synonyms.│
  193. │                   possible synonyms for a specified word.                  │
  194. │                   If synonyms are found a                                  │
  195. │                   PM list box is shown containing the possible new words.  │
  196. │                                                                            │
  197. └────────────────────────────────────────────────────────────────────────────┘
  198. */
  199. defproc synonym()
  200.    getline line                           /* get the current line          */
  201. compile if EVERSION >= '5.21'
  202.    line = translate(line, ' ', \9)  -- Convert tabs to spaces
  203. compile endif
  204.    if line<>'' then                       /* if it is NOT blank            */
  205.       i=.col                              /* get the current column number */
  206.       l=pos(' ',line,.col)                /* get possible word             */
  207.       if l=0 then                         /* could this be a word???       */
  208.          l=length(line)+1
  209.          if l<i then l=i endif
  210.       endif
  211.       wrd=strip(substr(line,i,l-i))       /* extract word candidate        */
  212.       oldwordlen=length(wrd)              /* save the length of the word   */
  213.       result=lexam(LXFVERFY,wrd)          /* authenticate word using lexam */
  214.       if result and wrd<>'' then          /* was it a success???             */
  215.          call strippunct(wrd,l,i)
  216.         .col=.col+i-1
  217.          result = lexam(LXFVERFY,wrd)
  218.       endif
  219.       if(result <> LXRFGOOD) then         /* was it a success ???          */
  220.          sayerror NO_MATCH__MSG '<'wrd'>' /* NO                      */
  221.          return ''                        /* exit function                 */
  222.       endif
  223.       /* It's a word!!!     */
  224.                                           /* get list of synonyms using lex*/
  225.       parse value lexam(LXFSYN,wrd) with 2 '/' result
  226.       if result='' then
  227.          sayerror NO_SYN__MSG '<'wrd'>'
  228.          return ''
  229.       endif
  230.  
  231. compile if EVERSION < 5.21  -- The old way
  232.       do forever
  233.          newword = listbox(SYNONYMS__MSG,'/'result,'/'REPLACE__MSG'/'CANCEL__MSG'/'HELP__MSG'/')
  234.          if newword<>3 then leave; endif
  235.          -- help was pressed
  236.          'helpmenu 14002'
  237.          return ''
  238.       enddo
  239. compile else
  240.       parse value listbox(SYNONYMS__MSG,'/'result,'/'REPLACE__MSG'/'CANCEL__MSG'/'HELP__MSG'/',0,0,0,0,
  241.  compile if EVERSION >= 5.60
  242.                           gethwndc(APP_HANDLE) || atoi(1) || atoi(1) || atoi(14002)) with button 2 newword \0
  243.  compile else
  244.                           atoi(1) || atoi(1) || atoi(14002) || gethwndc(APP_HANDLE)) with button 2 newword \0
  245.  compile endif
  246.       if button<>\1 then
  247.          newword = ''
  248.       endif
  249. compile endif -- EVERSION < 5.21
  250.       if newword<>'' then
  251. compile if EVERSION < 5.50  -- Don't have to worry about losing attributes...
  252.          getline line                           /* get the current line          */
  253.          replaceline leftstr(line,.col-1)||newword||substr(line,l)
  254. compile else
  255.          getsearch oldsearch
  256.          'xcom c '\1 || wrd || \1 || newword || \1
  257.          setsearch oldsearch
  258. compile endif
  259.          return length(newword)-oldwordlen
  260.       endif
  261.    endif
  262.  
  263. /*
  264. ╔════════════════════════════════════════════════════════════════════════════╗
  265. ║ Spell Checking Support                                                     ║
  266. ╚════════════════════════════════════════════════════════════════════════════╝
  267. */
  268.  
  269. compile if PROOF_DIALOG_FIXED
  270.    define DIALOG_POSN = ', -2, .windowwidth'
  271. compile elseif EVERSION < 5.21
  272.    define DIALOG_POSN = ' '
  273. compile else
  274.    define DIALOG_POSN = ', 0, 0 '
  275. compile endif
  276.  
  277. /*
  278. ┌────────────────────────────────────────────────────────────────────────────┐
  279. │ What's it called: proof()                                                  │
  280. │                                                                            │
  281. │ What does it do : The proof command uses E's lexam support to spell check  │
  282. │                   either the next word or a given word.  If a misspelled   │
  283. │                   word is encountered, a PM list box is shown containing   │
  284. │                   the possible corrections.                                │
  285. │                   syntax:   proof  [word]                                  │
  286. │                          - if 'word' is not specified, proof searchs for   │
  287. │                            the next word (after the cursor) and checks it. │
  288. └────────────────────────────────────────────────────────────────────────────┘
  289. */
  290. compile if not USE_CUSTOM_PROOF_DIALOG  --****************************************
  291. defc proof
  292.    universal ADDENDA_FILENAME
  293.    if load_lexam() then
  294.      return
  295.    endif
  296.    if arg(1)<>'' then
  297.       call proof1(arg(1))
  298.    else
  299.       call proof2()
  300.    endif
  301. compile if ADDENDASUPPORT
  302.    if addenda_filename<>'' then
  303.       call maybe_save_addenda()
  304.    endif
  305. compile endif
  306.    call drop_dictionary()
  307.    if arg(1)='' then
  308.       sayerror DONE__MSG
  309.    endif
  310.  
  311. /*
  312. ┌────────────────────────────────────────────────────────────────────────────┐
  313. │ What's it called: proof2()                                                 │
  314. │                                                                            │
  315. │ What does it do : Start at the current cursor position,  locate the next   │
  316. │                   word, and check the spelling of that word.   The spelling│
  317. │                   of each word is done by calling the lexam function.      │
  318. │                   The 'lexam' fuction is a internal                        │
  319. │                   opcode that uses the dynalink feature to access the      │
  320. │                   LEXAM.DLL                                                │
  321. │                                                                            │
  322. └────────────────────────────────────────────────────────────────────────────┘
  323. */
  324. defproc proof2
  325.    script_file_type=AMU_script_verification()
  326.    tex_file_type = (filetype() = 'TEX')
  327.  
  328.  --@@ If there's a line-marked area in the current file, proof only in there.
  329.  firstline=max(.line,1); lastline=.last; what = 'file'
  330.  if marktype() then  /* if no mark, default to entire file */
  331.     getfileid curfileid
  332.     getmark fl,ll,fc,lc,markfileid
  333.     if markfileid = curfileid then
  334.        firstline=fl; lastline=ll
  335.        what = 'marked area'
  336.     endif
  337.  endif
  338.  partial_lines = marktype()='BLOCK' | marktype()='CHAR'
  339.  
  340.  /* start checking at next word...*/
  341. ;getline line
  342. ;.col=1
  343. ;if leftstr(line,1)==' 'then
  344. ;   tabword
  345. ;endif
  346.  if partial_lines then .col=fc; else .col=1; endif
  347.  firstline
  348.  
  349.  for zz= firstline to lastline --@@
  350.    zz                                 /* advance to next (new) line         */
  351.    getline line
  352. compile if EVERSION >= '5.21'
  353.    line = translate(line, ' ', \9)  -- Convert tabs to spaces
  354. compile endif
  355. compile if EVERSION >= '5.21'
  356.    display -8
  357. compile endif
  358. ;  sayerror 'Spell Checking 'what'...'
  359.    sayerror 'Spell Checking 'what '(line' zz'; last='lastline')...'
  360. compile if EVERSION >= '5.21'
  361.    display 8
  362. compile endif
  363.  
  364.    loop
  365.  
  366.      if substr(line, .col, 1)=' ' & substr(line, .col)<>' ' then
  367.         tabword
  368.      endif
  369.      if partial_lines then
  370.         if .col>lc & (zz=lastline | marktype()='BLOCK') then
  371.            if marktype()='BLOCK' then .col=fc; endif
  372.            leave
  373.         endif
  374.      endif
  375.      l=pos(' ',line,.col)                /* find first word                 */
  376.      if not l then                       /* no more words on this line...   */
  377.         l=length(line)+1                 /* or there is only one word on    */
  378.         if l<=.col then                  /* the line...                     */
  379.            if marktype()='BLOCK' then .col=fc; else .col=1; endif
  380.            leave
  381.         endif
  382.      endif
  383.      wrd=substr(line,.col,l-.col)        /* extract word from line          */
  384.      if not verify(wrd, LEXAM_PUNCTUATION) then  -- No letters in "word"; skip it.
  385.         result = 0
  386.      else
  387.         result = lexam(LXFVERFY,wrd)        /* verify word using lexam         */
  388.      endif
  389.      if result and wrd<>'' then          /* was it a success???             */
  390.                                          /* YES, ignore script tags         */
  391.         if script_file_type then  -- Do just the cheap test first.
  392.            if (pos(leftstr(wrd,1),':&.') or pos(substr(line,max(.col-1,1),1),':&')) then
  393.               result=0
  394.               if leftstr(wrd,1)=':' then
  395.                  newl=pos('.',line,.col)
  396.                  if newl then
  397.                     l=newl
  398.                  endif
  399.               endif
  400.            endif
  401.         elseif tex_file_type & leftstr(wrd,1)='\' then
  402.            result=0
  403.         endif
  404.         if result then                 /* strip punctuation and try again */
  405.            call strippunct(wrd,l,i)
  406.           .col=.col+i-1
  407.            result = lexam(LXFVERFY,wrd)
  408.         endif
  409.      endif
  410.      if result and wrd<>'' then
  411. ;;      result = lexam(LXFVERFY,wrd)  -- Redundant???
  412. ;;      if result and wrd<>'' then
  413. compile if EVERSION < 5.21  -- Help is now handled by the dialog box
  414.            -- t=-3 means help was requested, so call spellword again.
  415.            t=-3
  416.            do while t=-3
  417. compile endif
  418. compile if ADDENDASUPPORT
  419.               t=spellword2(wrd, l, '/~Next/~Temp. Add')    -- spell check the word
  420. compile else
  421.               t=spellword2(wrd, l, '/~Next')               -- spell check the word
  422. compile endif
  423. compile if EVERSION < 5.21  -- Help is now handled by the dialog box
  424.            enddo
  425. compile endif
  426.            if t=0 then                         -- error occured
  427.               return 0
  428.            endif
  429.            if t>0 then
  430.               l=l + t - 100
  431.            elseif t=-4 then   -- Edit was selected.
  432.               l = .col -1     -- (so .col won't change; recheck from current point)
  433.            endif
  434.            getline line
  435. compile if EVERSION >= '5.21'
  436.            line = translate(line, ' ', \9)  -- Convert tabs to spaces
  437. compile endif
  438. ;;      endif
  439.      endif
  440.      .col=l+1
  441.    endloop
  442.  endfor
  443.  
  444. /*
  445. ┌────────────────────────────────────────────────────────────────────────────┐
  446. │ What's it called: spellword()                                              │
  447. │                                                                            │
  448. │ What does it do : Check the word at the cursor position, removing          │
  449. │                   punctuation characters.  It is assumed that the cursor   │
  450. │                   is positioned at the beginning of the word.  (Used by    │
  451. │                   proof2 and proofword.)  If it's a valid word then check  │
  452. │                   the spelling of the word using the lexam opcode.  If a   │
  453. │                   valid result is returned place it in a PM list box using │
  454. │                   the 'listbox' procedure.  Returns the length of the word │
  455. │                   found.  The optional argument is a string containing a   │
  456. │                   button name.  E.g., '/Next'                              │
  457. └────────────────────────────────────────────────────────────────────────────┘
  458. */
  459. defproc spellword
  460.    getline line                              /* ignore script tags           */
  461. compile if EVERSION >= '5.21'
  462.    line = translate(line, ' ', \9)  -- Convert tabs to spaces
  463. compile endif
  464.    if line<>'' then                          /* if the line is not empty...  */
  465.       i=.col                                 /* save the cursor column       */
  466.       l=pos(' ',line,.col)                   /* get next word after cursor   */
  467.       if l=0 then                            /* is it a word???              */
  468.          l=max(length(line)+1, i)
  469.       endif
  470.       wrd=strip(substr(line,i,l-i))          /* extract word from line       */
  471.       result = lexam(LXFVERFY,wrd)           /* verify word                  */
  472.       if result and wrd<>'' then             /* was it a success             */
  473.          start_l = l
  474.          do forever
  475.             call strippunct(wrd,l,i)            /* strip punctuation/ try again */
  476.             .col=.col+i-1                       /* move to next column          */
  477.             if l>=arg(2) | wrd='' then  -- Will always be true if arg(2) omitted.
  478.                leave
  479.             endif
  480.             .col = l
  481.             l = start_l
  482.             wrd=strip(substr(line,.col,l-.col))    /* extract word from line       */
  483.          enddo
  484.          result = lexam(LXFVERFY,wrd)        /* try word  verification again */
  485.       endif
  486.       if (result or abbrev('FORCE', upcase(arg(3)), 1)) and wrd<>'' then             /* was it a success             */
  487.           return spellword2(wrd, l, arg(1))
  488.       else
  489.          --.messageline='word is spelled correctly'
  490.          return -2
  491.       endif
  492.    endif
  493.    return 0
  494.  
  495. defproc spellword2(wrd, l)
  496.          oldwordlen=length(wrd)              /* yes it's a word.....         */
  497.                                              /* use lexam to spell check word*/
  498.          refresh
  499.          parse value lexam(LXFSPAID,wrd) with 2 '/' result
  500.          if rc>=LXRFINIT then
  501.             sayerror LOOKUP_FAILED__MSG '<' wrd '> RC='rc
  502.             return -1  -- next word
  503.          else
  504.             if result='' then
  505.                result='*Nothing Found*'
  506.             endif
  507.             oldcol = .col; .col = .col + oldwordlen; .col = oldcol;
  508. compile if EVERSION < '5.50'
  509.             refresh
  510.             sayat wrd, .cursory, .cursorx,
  511.                   .textcolor%16+(.textcolor // 16)*16, oldwordlen
  512. compile elseif EVERSION >= 5.60
  513.             circleit PROOF_CIRCLE_STYLE, .line, .col, .col+oldwordlen-1, PROOF_CIRCLE_COLOR1, PROOF_CIRCLE_COLOR2
  514.             refresh  -- Refresh required to display circle, because control isn't being returned to the user
  515. compile else
  516.             circleit PROOF_CIRCLE_STYLE, .line, .col, .col+oldwordlen-1, 1 -- color irrelevant now
  517.             refresh  -- Refresh required to display circle, because control isn't being returned to the user
  518. compile endif
  519. compile if ADDENDASUPPORT
  520.  compile if EVERSION < 5.21  -- The old way
  521.             newword=listbox(PROOF__MSG '<'wrd'>', '/'result,
  522.                             '/'REPLACE__MSG'/'CANCEL__MSG||arg(3)'/'ADD__MSG'/'EDIT__MSG'.../'HELP__MSG $DIALOG_POSN)   -- put result in PM list box
  523.  compile else
  524.             parse value listbox(PROOF__MSG '<'wrd'>', '/'result,
  525.                                 '/'REPLACE__MSG'/'CANCEL__MSG||arg(3)'/'ADD__MSG'/'EDIT__MSG'.../'HELP__MSG $DIALOG_POSN ,0,0,
  526.   compile if EVERSION >= 5.60
  527.                                 gethwndc(APP_HANDLE) || atoi(1) || atoi(1) || atoi(14000)) with button 2 newword \0
  528.   compile else
  529.                                 atoi(1) || atoi(1) || atoi(14000) || gethwndc(APP_HANDLE)) with button 2 newword \0
  530.   compile endif
  531.             if button=\0 | button=\2 then  -- Close or Cancel
  532.                newword = ''
  533.             endif
  534.  compile endif -- EVERSION < 5.21
  535.             if arg(3)='' then
  536.                butlist='7 7 3 4 5'  -- Next; Temp. Add; Add; Edit; Help
  537.             else
  538.                butlist='3 4 5 6 7'  -- Next; Temp. Add; Add; Edit; Help
  539.             endif
  540. compile else
  541.  compile if EVERSION < 5.21  -- The old way
  542.             newword=listbox(PROOF__MSG '<'wrd'>','/'result,'/'REPLACE__MSG'/'CANCEL__MSG ||arg(3)'/'EDIT__MSG'.../'HELP__MSG $DIALOG_POSN)  -- put result in PM list box
  543.  compile else
  544.             parse value listbox(PROOF__MSG '<'wrd'>', '/'result,
  545.                                 '/'REPLACE__MSG'/'CANCEL__MSG||arg(3)'/'EDIT__MSG'.../'HELP__MSG $DIALOG_POSN ,0,0,
  546.   compile if EVERSION >= 5.60
  547.                                 gethwndc(APP_HANDLE) || atoi(1) || atoi(1) || atoi(14000)) with button 2 newword \0
  548.   compile else
  549.                                 atoi(1) || atoi(1) || atoi(14000) || gethwndc(APP_HANDLE)) with button 2 newword \0
  550.   compile endif
  551.             if button=\0 | button=\2 then  -- Close or Cancel
  552.                newword = ''
  553.             endif
  554.  compile endif -- EVERSION < 5.21
  555.             if arg(3)='' then
  556.                butlist='7 7 7 3 4'  -- Next; Temp. Add; Add; Edit; Help
  557.             else
  558.                butlist='3 7 7 4 5'  -- Next; Temp. Add; Add; Edit; Help
  559.             endif
  560. compile endif
  561.             parse value butlist with but_next but_temp_add but_add but_edit but_help
  562. compile if EVERSION < 5.21  -- Help is now handled by the dialog box
  563.             if newword=but_help then
  564.                'helpmenu 14000'
  565.                return -3     -- do line over again
  566.             endif
  567.             if newword=but_edit then
  568. compile else
  569.             if button=chr(but_edit) then
  570. compile endif
  571.                newword=entrybox(REPLACEMENT__MSG '<'wrd'>','/'REPLACE__MSG'/'CANCEL__MSG,wrd)
  572.                if newword='' then
  573.                   return -1  -- next word
  574.                endif
  575. compile if EVERSION < 5.50  -- Don't have to worry about losing attributes...
  576.                getline line
  577.                replaceline leftstr(line,.col-1)||newword||substr(line,l)
  578. compile else
  579.                getsearch oldsearch
  580.                'xcom c '\1 || wrd || \1 || newword || \1
  581.                setsearch oldsearch
  582. compile endif
  583.                refresh
  584. ;;             return -100 - (length(newword)-oldwordlen)    -- Don't care about new len.
  585.                return -4    -- re-check line
  586.             endif
  587. compile if EVERSION < '5.50'
  588.             sayat wrd, .cursory, .cursorx, .textcolor, oldwordlen
  589. compile else
  590. ;           refresh  -- maybe can leave out...
  591. compile endif
  592. compile if EVERSION < 5.21
  593.             if newword=but_next then   -- goto next word
  594. compile else
  595.             if button=chr(but_next) then   -- goto next word
  596. compile endif
  597.                return -1
  598.             endif
  599. compile if ADDENDASUPPORT
  600.  compile if EVERSION < 5.21
  601.             if newword=but_temp_add then   -- temporary addenda (just for this PROOF session)
  602.  compile else
  603.             if button=chr(but_temp_add) then   -- goto next word
  604.  compile endif
  605.  compile if RESPECT_CASE_FOR_ADDENDA
  606.                call lexam(LXFAD2TRS, wrd)
  607.  compile else
  608.                call lexam(LXFAD2TRS,lowcase(wrd))
  609.  compile endif
  610.                return -1
  611.             endif
  612.  compile if EVERSION < 5.21
  613.             if newword=but_add then   -- addenda
  614.  compile else
  615.             if button=chr(but_add) then   -- goto next word
  616.  compile endif
  617.                call AMU_addenda_addition_processing(wrd)
  618.                return -1
  619.             endif
  620. compile endif
  621.             if newword='*Nothing Found*' then
  622.                return -1
  623.             endif
  624.             if newword<>'' then              /* was it a valid result ???    */
  625.                                              /* replace word in line         */
  626. compile if EVERSION < 5.50  -- Don't have to worry about losing attributes...
  627.                getline line
  628.                replaceline leftstr(line,.col-1)||newword||substr(line,l)
  629.                refresh
  630. compile else
  631.                getsearch oldsearch
  632.                'xcom c '\1 || wrd || \1 || newword || \1
  633.                setsearch oldsearch
  634. compile endif
  635.                return 100 + length(newword)-oldwordlen
  636. ;              return -1
  637.             endif
  638.           endif
  639.    return 0
  640.  
  641. /*
  642. ┌────────────────────────────────────────────────────────────────────────────┐
  643. │ What's it called: proof1()                                                 │
  644. │                                                                            │
  645. │ What does it do : Takes a word argument and looks it up in the lexam       │
  646. │                   dictionary using the 'lexam' opcode.                     │
  647. │                   If the word is found a list box is presented with the    │
  648. │                   possible correct word choices.                           │
  649. └────────────────────────────────────────────────────────────────────────────┘
  650. */
  651. defproc proof1( wrd )
  652.    result = lexam(LXFVERFY,wrd)            /* first off, is it a word?    */
  653.    if result then                          /* well is it???               */
  654.       result = lexam(LXFSPAID,wrd)         /* YES, now check it with lexam*/
  655.  
  656.       parse value result with .'/' result  /* remove first word           */
  657.       if rc>=LXRFINIT then
  658.          sayerror LOOKUP_FAILED__MSG '<' wrd '>'
  659.       else
  660.          if result='' then
  661.             result='*Nothing Found*'
  662.          endif
  663. compile if EVERSION < 5.21  -- The old way
  664.          do forever
  665.  compile if ADDENDASUPPORT
  666.             newword=listbox(PROOF_WORD__MSG,'/'result,'/'REPLACE__MSG'/'EXIT__MSG'/'ADD__MSG'/'HELP__MSG)     /* put result in PM list box   */
  667.             if newword='3' then   --  addenda
  668.                call AMU_addenda_addition_processing(wrd)
  669.                return -1
  670.             endif
  671.             if newword<>4 then leave; endif
  672.  compile else
  673.             newword=listbox(PROOF_WORD__MSG,'/'strip(result),'/'REPLACE__MSG'/'EXIT__MSG'/'HELP__MSG)     /* put result in PM list box   */
  674.             if newword<>3 then leave; endif
  675.  compile endif
  676.             'helpmenu 14001'
  677.          enddo
  678. compile else
  679.          parse value listbox(PROOF_WORD__MSG, '/'result,
  680.  compile if ADDENDASUPPORT
  681.                              '/'REPLACE__MSG'/'EXIT__MSG'/'ADD__MSG'/'HELP__MSG,
  682.  compile else
  683.                              '/'REPLACE__MSG'/'EXIT__MSG'/'HELP__MSG
  684.  compile endif
  685.  compile if EVERSION >= 5.60
  686.                              gethwndc(APP_HANDLE) || atoi(1) || atoi(1) || atoi(14001)) with button 2 newword \0
  687.  compile else
  688.                              atoi(1) || atoi(1) || atoi(14001) || gethwndc(APP_HANDLE)) with button 2 newword \0
  689.  compile endif
  690.          if button=\0 | button=\2 then  -- Close or Cancel
  691.             newword = ''
  692.  compile if ADDENDASUPPORT
  693.          elseif button=\3 then   --  addenda
  694.             call AMU_addenda_addition_processing(wrd)
  695.             return -1
  696.  compile endif
  697.          endif
  698. compile endif -- EVERSION < 5.21
  699.          if newword='*Nothing Found*' then
  700.             return
  701.          endif
  702.          return newword
  703.       endif
  704.    endif
  705.  
  706. compile endif  -- not USE_CUSTOM_PROOF_DIALOG  *************************************
  707.  
  708. /*
  709. ╔════════════════════════════════════════════════════════════════════════════╗
  710. ║ Addenda Support                                                            ║
  711. ╚════════════════════════════════════════════════════════════════════════════╝
  712. */
  713. compile if ADDENDASUPPORT
  714. /*
  715. ┌────────────────────────────────────────────────────────────────────────────┐
  716. │ What's it called: maybe_save_addenda                                       │
  717. │                                                                            │
  718. │ What does it do :                                                          │
  719. │                                                                            │
  720. └────────────────────────────────────────────────────────────────────────────┘
  721. */
  722. ; Addenda support commands
  723.  
  724. defproc maybe_save_addenda
  725.    universal  addenda_has_been_modified
  726.    universal  AMU_addenda_file_identification
  727.    universal  ADDENDA_FILENAME
  728.  
  729. ;   if addenda_has_been_modified then
  730.      -- sayatbox 'saving addenda 'ADDENDA_FILENAME
  731.       if AMU_addenda_file_identification<>''  then
  732.        getfileid AMU_current_file_identification
  733.        rc = 0
  734.        activatefile AMU_addenda_file_identification
  735.        if not rc then
  736.           if .modify then 'xcom save'; endif
  737. ;;        'xcom quit'
  738.        endif
  739.        -- sayerror 'addenda file filed'
  740.        activatefile AMU_current_file_identification
  741.       endif
  742.       addenda_has_been_modified=0
  743.       -- sayerror 0
  744. ;  endif
  745.  
  746. ;defc AMU_addenda_pickup
  747. ;   universal  ADDENDA_FILENAME
  748. ;   call lexam(LXFAMUGDIC,ADDENDA_FILENAME)
  749.  
  750. ;defc AMU_addenda_addition
  751. ;   call lexam(LXFAD2TRS,arg(1))
  752.  
  753. defproc AMU_addenda_processing
  754.    universal AMU_addenda_file_identification
  755.    universal  ADDENDA_FILENAME
  756.    getfileid AMU_current_file_identification
  757.    'xcom e' ADDENDA_FILENAME
  758.    -- sayerror 'addenda file loaded'
  759.    if not rc or rc = sayerror('New file') then
  760.       getfileid AMU_addenda_file_identification
  761.    else
  762.       AMU_addenda_file_identification =''
  763.       sayerror BAD_ADDENDA__MSG ADDENDA_FILENAME 'rc=' rc
  764.       stop
  765.    endif
  766.    .visible=0 -- hidden file
  767.    activatefile AMU_current_file_identification
  768.    if AMU_addenda_file_identification <>'' then
  769.       for i = 1 to AMU_addenda_file_identification.last
  770.          getline line,i,AMU_addenda_file_identification
  771.          if upcase(leftstr(line, 8))='.DU ADD ' then
  772.             line=substr(line,9)
  773.          endif
  774.          do while line <> ''
  775.             parse value line with wrd line
  776.  compile if RESPECT_CASE_FOR_ADDENDA
  777.             call lexam(LXFAD2TRS,wrd)
  778.  compile else
  779.             call lexam(LXFAD2TRS,lowcase(wrd))
  780.  compile endif
  781.          enddo
  782.       endfor
  783.    endif
  784.  
  785. defproc AMU_addenda_addition_processing(AMU_addenda_entry)
  786.    universal  addenda_has_been_modified
  787.    universal AMU_addenda_file_identification, ADDENDA_FILENAME
  788.    addenda_has_been_modified=1
  789.  compile if not RESPECT_CASE_FOR_ADDENDA
  790.    AMU_addenda_entry=lowcase(AMU_addenda_entry)
  791.  compile endif
  792.    call lexam(LXFAD2TRS,AMU_addenda_entry)
  793.    if ADDENDA_FILENAME<>'' & AMU_addenda_file_identification<>'' then
  794.       insertline AMU_addenda_entry,AMU_addenda_file_identification.last+1,AMU_addenda_file_identification
  795.    endif
  796.  
  797.  
  798. compile endif -- ADDENDASUPPORT
  799.  
  800. ; The following is a script file type verification algorithm
  801. ; suggested by Larry Margolis. (Thanks, Larry)
  802. defproc AMU_script_verification()
  803.    ext=filetype()
  804. compile if defined(my_SCRIPT_FILE_TYPE)
  805.    return ext='SCR' or ext='SCT' or ext='SCRIPT' or ext='IPF' or ext=my_SCRIPT_FILE_TYPE
  806. compile else
  807.    return ext='SCR' or ext='SCT' or ext='SCRIPT' or ext='IPF'
  808. compile endif
  809.  
  810.  
  811. /*
  812. ╔════════════════════════════════════════════════════════════════════════════╗
  813. ║ General Lexam Support                                                      ║
  814. ╚════════════════════════════════════════════════════════════════════════════╝
  815. */
  816. defproc load_lexam
  817.    universal DICTIONARY_FILENAME
  818.    universal ADDENDA_FILENAME
  819.    universal Dictionary_loaded
  820.    if not dictionary_loaded then
  821.       rc = 0
  822.       result = lexam(LXFINIT)
  823.       if (result<>LXRFGOOD and result<>LXRFIFCN) or rc=-322 then
  824.          if result='febe' or rc=-322 then  -- x'febe' = -322 = sayerror('Dynalink: unrecognized library name')
  825. compile if EVERSION < '5.60a'  -- 5.60a and above give the message internally
  826.             sayerror sayerrortext(-322) LEXAM_DLL'.DLL'
  827. compile endif
  828.          else
  829.             sayerror INIT_ERROR__MSG '('rc')'
  830.          endif
  831.          return 1
  832.       endif
  833.       dictlist=DICTIONARY_FILENAME
  834.       do while dictlist <> ''
  835.          parse value dictlist with dictionary dictlist
  836.          if not(verify(dictionary,'\:','M')) then
  837.             if not exist(dictionary) then
  838.                findfile destfilename, dictionary, '','D'
  839.                if not rc then dictionary = destfilename; endif
  840.             endif
  841.          endif
  842.          result=lexam(LXFGDIC, dictionary)
  843.          if result>=LXRFNFND & result<>LXRFDUPD then  -- Duplicate Dictionary; didn't unload?
  844.             if exist(dictionary) then
  845.                sayerror BAD_DICT__MSG '"'dictionary'";' ERROR__MSG result
  846.             else
  847.                sayerror NO_DICT__MSG '"'dictionary'"'
  848.             endif
  849.             return 1
  850.          endif
  851.       enddo
  852.       Dictionary_loaded = 1
  853. compile if ADDENDASUPPORT
  854.       if ADDENDA_FILENAME<>'' then
  855.          result = lexam(LXFAMUGDIC,ADDENDA_FILENAME)
  856.          if result & result<>LXRFUPDC then
  857.             sayerror BAD_ADDENDA__MSG '"'ADDENDA_FILENAME'";' ERROR__MSG result
  858.          else
  859.             call AMU_addenda_processing()
  860.          endif
  861.       endif
  862. compile endif
  863.    endif
  864.    dictionary_loaded = dictionary_loaded + 1
  865.    return 0
  866.  
  867. defproc drop_dictionary
  868.    universal DICTIONARY_FILENAME
  869.    universal  ADDENDA_FILENAME
  870.    universal  Dictionary_loaded
  871.    if dictionary_loaded then
  872.       dictionary_loaded = dictionary_loaded - 1
  873.    endif
  874.    if not dictionary_loaded then  -- Only unload if use-count now 0.
  875.       dictlist=DICTIONARY_FILENAME
  876.       do while dictlist <> ''
  877.          parse value dictlist with dictionary dictlist
  878.          call lexam(LXFFDIC, dictionary);
  879.       enddo
  880. compile if ADDENDASUPPORT
  881.       if ADDENDA_FILENAME<>'' then
  882.          call lexam(LXFFDIC,ADDENDA_FILENAME);
  883.       endif
  884. compile endif
  885.       call lexam(LXFTERM)
  886.    endif
  887.  
  888. defproc strippunct(var wrd,var l,var i)
  889.    /* strip leading and trailing punctuation and try again*/
  890.    i=verify(wrd, LEXAM_PUNCTUATION)
  891.    if i then
  892.       j = length(wrd)
  893.       do while pos(substr(wrd, j, 1), '.?!,:;')  -- Extra check, to accept "didn't."
  894.          j = j - 1
  895.       enddo
  896.       if j<length(wrd) then
  897.          if not lexam(LXFVERFY, leftstr(wrd, j)) then  -- If result is 0, word is good.
  898.             i = 1
  899. ;;          l = l - length(wrd) + j
  900.             wrd = leftstr(wrd, j)
  901.             return
  902.          endif
  903.       endif
  904.       l=l-length(wrd)
  905.       wrd=substr(wrd,i)
  906.       j=verify(wrd, LEXAM_PUNCTUATION,'m')
  907.       if j then
  908.          wrd=leftstr(wrd,j-1)
  909.       else
  910.          j=length(wrd)+1
  911.       endif
  912.       l=l+j+i-2
  913.    else
  914.       i=length(wrd)+1
  915.    endif
  916.  
  917. compile if not USE_CUSTOM_PROOF_DIALOG
  918. defc proofword,verify
  919.    universal ADDENDA_FILENAME
  920.    if load_lexam() then
  921.      return
  922.    endif
  923.    orig_col = .col
  924.    call pbegin_word()
  925.    if substr(textline(.line), orig_col, 1)=' ' & .col < orig_col then
  926.       tmp = .col
  927.       call pend_word()
  928.       orig_col = .col
  929.       .col = tmp
  930.    endif
  931.    spellrc = spellword('', orig_col, arg(1))
  932. compile if ADDENDASUPPORT
  933.    if addenda_filename<>'' then
  934.       call maybe_save_addenda()
  935.    endif
  936. compile endif
  937.    call drop_dictionary()
  938.    if -2 = spellrc then
  939.       sayerror SPELLED_OK__MSG
  940.    endif
  941. compile endif -- not USE_CUSTOM_PROOF_DIALOG
  942.  
  943. defc dict
  944.    universal DICTIONARY_FILENAME
  945.    dictlist = arg(1)
  946.    if dictlist='' then
  947.       sayerror DICTLIST_IS__MSG DICTIONARY_FILENAME
  948.       return
  949.    endif
  950.    do while dictlist <> ''
  951.       parse value dictlist with dictionary dictlist
  952.       if not exist(dictionary) then
  953.          sayerror FILE_NOT_FOUND__MSG '"'dictionary'"; 'DICT_REMAINS__MSG DICTIONARY_FILENAME
  954.          return
  955.       endif
  956.    enddo
  957.    DICTIONARY_FILENAME = arg(1)
  958.  
  959. compile if EVERSION >= 5.60
  960. defc newproof
  961.    universal ADDENDA_FILENAME
  962.    if load_lexam() then
  963.      return
  964.    endif
  965.    script_file_type=AMU_script_verification()
  966.    tex_file_type = (filetype() = 'TEX')
  967.  
  968.  --@@ If there's a line-marked area in the current file, proof only in there.
  969.    firstline=max(.line,1); lastline=.last; what = 'file'
  970.    if marktype() then  /* if no mark, default to entire file */
  971.       getfileid curfileid
  972.       getmark fl,ll,fc,lc,markfileid
  973.       if markfileid = curfileid then
  974.          firstline=fl; lastline=ll
  975.          what = 'marked area'
  976.       endif
  977.    endif
  978.    partial_lines = marktype()='BLOCK' | marktype()='CHAR'
  979.  
  980. ;; if partial_lines then .col=fc; else .col=1; endif
  981.  
  982.    while firstline<=lastline do
  983.  compile if EVERSION >= '5.21'
  984.       display -8
  985.  compile endif
  986.       sayerror 'Spell Checking 'what'...'
  987. ;;    sayerror 'Spell Checking 'what '(line' zz'; last='lastline')...'
  988.  compile if EVERSION >= '5.21'
  989.       display 8
  990.  compile endif
  991.       .col = 1
  992.  rc = '[not set]'
  993.       result = lexam(LXFPRFLINE, firstline, lastline)
  994.       if length(result) then
  995.  sayerror 'rc=' rc'; result =' c2x(result)
  996.          firstline = ltoa(leftstr(result, 4), 10)
  997.          if length(result)=4 then sayerror 'Unexpected error on line' firstline'; aborting.'; stop; endif
  998.          firstline
  999.          offst = 0
  1000.          oldlen = length(textline(firstline))
  1001.          do i = 5 to length(result) by 2
  1002.             .col = itoa(substr(result, i, 2), 10) + offst
  1003.  compile if ADDENDASUPPORT
  1004.             t=spellword('/~Next/~Temp. Add')    -- spell check the word
  1005.  compile else
  1006.             t=spellword('/~Next')               -- spell check the word
  1007.  compile endif
  1008.             if t=0 then                         -- error occured
  1009.                return 0
  1010.             endif
  1011.             if t>0 then
  1012.                offst = offst + t - 100
  1013.             elseif t=-4 then   -- Edit was selected.
  1014.                i = i - 2  -- Repeat at this position.  (???)
  1015.                newlen = length(textline(firstline))
  1016.                offst = offst + newlen - oldlen
  1017.                oldlen = newlen
  1018.             endif
  1019.          enddo
  1020.          firstline = firstline + 1
  1021.       else  -- proofed the entire block successfully
  1022.          leave
  1023.       endif
  1024.    endwhile
  1025.  
  1026.  compile if ADDENDASUPPORT
  1027.    if addenda_filename<>'' then
  1028.       call maybe_save_addenda()
  1029.    endif
  1030.  compile endif
  1031.    call drop_dictionary()
  1032.    if arg(1)='' then
  1033.       sayerror DONE__MSG
  1034.    endif
  1035.  
  1036. compile endif  -- >= 5.60
  1037.  
  1038. compile if USE_CUSTOM_PROOF_DIALOG
  1039. ; New commands for use with custom Proof dialog.
  1040.  
  1041. ; Proof - proofs the document or marked area.
  1042. ;    It uses the new Lexam subop that proofs lines and doesn't stop
  1043. ;    until it hits an error or finishes the last line.
  1044. ; ProofWord - proofs the current word.
  1045.  
  1046. ; Both set up state information, then call SpellWordD (like SpellWord) to check
  1047. ; an individual word.  If SpellWordD decides the word is bad, then if the dialog
  1048. ; has been started, it tells it to display the word, otherwise it starts the
  1049. ; dialog and relies on the Init message coming from the dialog to tell the dialog
  1050. ; to show the word.
  1051.  
  1052. ; State information:
  1053. ;  proofdlg_hwnd      Proof Dialog's window handle
  1054. ;  proofdlg_whatflag  What we're proofing - 1 = file, 2 = mark, 3 = word
  1055. ;  proof_curline      Current line we're checking
  1056. ;  proof_lastline     Last line to be checked
  1057. ;  proof_lexresult    Result from Lexam(proofline)
  1058. ;  proof_resultofs    Current offset in proof_lexresult we're checking
  1059. ;  proof_offst        offset from the columns in proof_lexresult we should use
  1060. ;                     (changes from 0 if we replace an earlier word in that line
  1061. ;                     with one of a different length)
  1062. ;  proof_prev_col     Saves the previous column (to be used after replacing
  1063. ;                     a word with a user-entered word; we need to use the old offset,
  1064. ;                     not the new one).
  1065.  
  1066. defc proof
  1067.    universal proofdlg_hwnd, proofdlg_whatflag, proof_curline, proof_lastline, proof_lexresult, proofdlg_filetypeflags, proof_word
  1068.    if load_lexam() then
  1069.       return
  1070.    endif
  1071.  
  1072.    if arg(1)<>'' then  -- A word to be proofed was given as an argument.
  1073.       proofdlg_whatflag = 4
  1074.       result = lexam(LXFVERFY,arg(1))           /* verify word                  */
  1075.       if not result then    -- was it a success
  1076.          sayerror 'word is spelled correctly'
  1077.          return
  1078.       endif
  1079.       proof_word = arg(1)
  1080.       if proofdlg_hwnd then  -- Dialog started
  1081.          'proofdlg' proofdlg_hwnd 'newword'
  1082.       else
  1083.          sayerror 0        -- (Clear a "Spell checking..." message, if one was up.)
  1084.          'proofdlg pop'    -- Start the dialog; it will do the rest
  1085.       endif
  1086.       return
  1087.    endif
  1088.  
  1089. ;  script_file_type=AMU_script_verification()
  1090. ;  tex_file_type = (filetype() = 'TEX')
  1091.    proofdlg_filetypeflags = AMU_script_verification() + 2*(filetype() = 'TEX')
  1092.  
  1093.  --@@ If there's a line-marked area in the current file, proof only in there.
  1094.    proof_curline=max(.line,1); proof_lastline=.last; what = 'file'; proofdlg_whatflag = 1
  1095.    if marktype() then  /* if no mark, default to entire file */
  1096.       getfileid curfileid
  1097.       getmark fl,ll,fc,lc,markfileid
  1098.       if markfileid = curfileid then
  1099.          proof_curline=fl; proof_lastline=ll
  1100.          what = 'marked area'
  1101.          proofdlg_whatflag = 2
  1102.       endif
  1103.    endif
  1104.    partial_lines = marktype()='BLOCK' | marktype()='CHAR'
  1105.  
  1106. ;; if partial_lines then .col=fc; else .col=1; endif
  1107.    proof_lexresult = ''
  1108.    'keep_on_prufin'
  1109.  
  1110. defc keep_on_prufin
  1111.    universal ADDENDA_FILENAME
  1112.    universal proofdlg_hwnd, proofdlg_whatflag, proof_curline, proof_lastline, proof_lexresult, proof_resultofs, proof_offst, proof_prev_col, proofdlg_filetypeflags
  1113.    while proof_curline<=proof_lastline do
  1114.       if not proofdlg_hwnd then
  1115.          display -8
  1116.          sayerror 'Spell Checking 'subword('file marked area', proofdlg_whatflag, proofdlg_whatflag)'...'
  1117.          display 8
  1118. ;;    else
  1119. ;;       msg = 'Checking spelling...'\0
  1120. ;;       call windowmessage(1,  proofdlg_hwnd,   -- send message back to dialog
  1121. ;;                          32,               -- WM_COMMAND - 0x0020
  1122. ;;                          9190,             -- Set dialog prompt
  1123. ;;                          ltoa(offset(msg) || selector(msg), 10) )
  1124.       endif
  1125.       if proof_lexresult='' then
  1126.          .col = 1
  1127.          proof_lexresult = lexam(LXFPRFLINE, proof_curline, proof_lastline, proofdlg_filetypeflags)
  1128. ;sayerror 'proof_lexresult('proof_curline',' proof_lastline') =' c2x(leftstr(proof_lexresult,4)) c2x(substr(proof_lexresult, 5))
  1129.          proof_resultofs = 5
  1130.          proof_offst = 0
  1131.          proof_prev_col = ''
  1132.       endif
  1133.       if length(proof_lexresult) then
  1134. ;sayerror 'rc=' rc'; proof_lexresult =' c2x(proof_lexresult)
  1135.          proof_curline = ltoa(leftstr(proof_lexresult, 4), 10)
  1136.          if length(proof_lexresult)=4 then
  1137.             sayerror 'Unexpected error on line' proof_curline '- skipping to next line.'
  1138.             proof_curline = proof_curline + 1
  1139.             proof_lexresult=''
  1140.             iterate
  1141.          endif
  1142.          proof_curline
  1143.          oldlen = length(textline(proof_curline))
  1144.          do i = proof_resultofs to length(proof_lexresult) by 2
  1145.             if proof_prev_col then
  1146.                .col = proof_prev_col
  1147.             else
  1148.                .col = itoa(substr(proof_lexresult, i, 2), 10) + proof_offst
  1149.             endif
  1150.             t=spellwordd('')    -- spell check the word
  1151. ;sayerror 'i='i'; .col =' .col '=' itoa(substr(proof_lexresult, i, 2), 10) + proof_offst'; proof_offst='proof_offst 't='t
  1152.             if t = -3 then  -- Dialog will continue
  1153.                proof_resultofs = i + 2
  1154.                return
  1155.             endif
  1156.             proof_prev_col=''
  1157.             if not t then                         -- error occured
  1158.                leave
  1159.             endif
  1160.          enddo
  1161.          proof_curline = proof_curline + 1
  1162.          proof_lexresult = ''
  1163.       else  -- proofed the entire block successfully
  1164.          leave
  1165.       endif
  1166.    endwhile
  1167.  
  1168.  compile if ADDENDASUPPORT
  1169.    if addenda_filename<>'' then
  1170.       call maybe_save_addenda()
  1171.    endif
  1172.  compile endif
  1173.    call drop_dictionary()
  1174.    if proofdlg_hwnd then
  1175.       call windowmessage(0,  proofdlg_hwnd,   -- send message to dialog
  1176.                          41,                  -- WM_CLOSE - 0x0029
  1177.                          0,
  1178.                          0)
  1179.    endif
  1180.    if arg(1)='' then
  1181.       sayerror DONE__MSG
  1182.    endif
  1183.  
  1184.  
  1185. defc proofword, verify
  1186.    universal ADDENDA_FILENAME
  1187.    universal proofdlg_hwnd, proofdlg_whatflag
  1188.    if load_lexam() then
  1189.      return
  1190.    endif
  1191.    orig_col = .col
  1192.    call pbegin_word()
  1193.    if substr(textline(.line), orig_col, 1)=' ' & .col < orig_col then
  1194.       tmp = .col
  1195.       call pend_word()
  1196.       orig_col = .col
  1197.       .col = tmp
  1198.    endif
  1199.    proofdlg_whatflag = 3
  1200.    spellrc = spellwordd('', orig_col, arg(1))
  1201.    if -2 = spellrc then
  1202.       sayerror SPELLED_OK__MSG
  1203. ;;    if addenda_filename<>'' then
  1204. ;;       call maybe_save_addenda()
  1205. ;;    endif
  1206.       call drop_dictionary()
  1207.               -- Otherwise, closing the dialog will unload lexam.
  1208.    endif
  1209.  
  1210. ; return codes:  0 = unexpected error
  1211. ;       X       >0 = 100 + length(newword)-length(oldword)
  1212. ;       X       -1 = Lookup failed or user selected Next or (Temp)Add; go on to next word.
  1213. ;               -2 = Word was spelled correctly
  1214. ;               -3 = Dialog invoked
  1215. ;       X       -4 = User selected Edit; recheck line.
  1216. defproc spellwordd
  1217.    universal proofdlg_hwnd, proof_word
  1218.    getline line
  1219.    line = translate(line, ' ', \9)  -- Convert tabs to spaces
  1220.    if line='' then                        /* if the line is empty...     */
  1221.       return 0
  1222.    endif
  1223.    i=.col                                 /* save the cursor column       */
  1224.    l=pos(' ',line,.col)                   /* get next word after cursor   */
  1225.    if l=0 then                            /* is it a word???              */
  1226.       l=max(length(line)+1, i)
  1227.    endif
  1228.    wrd=strip(substr(line,i,l-i))          /* extract word from line       */
  1229.    if wrd='' then
  1230.       return -2
  1231.    endif
  1232.    result = lexam(LXFVERFY,wrd)           /* verify word                  */
  1233.    if result then                         /* was it a success             */
  1234.       start_l = l
  1235.       do forever
  1236.          call strippunct(wrd,l,i)            /* strip punctuation/ try again */
  1237.          .col=.col+i-1                       /* move to next column          */
  1238.          if wrd='' then
  1239.             return -2
  1240.          endif
  1241.          if l>=arg(2) then  -- Will always be true if arg(2) omitted.
  1242.             leave
  1243.          endif
  1244.          .col = l
  1245.          l = start_l
  1246.          wrd=strip(substr(line,.col,l-.col))    /* extract word from line       */
  1247.       enddo
  1248.       result = lexam(LXFVERFY,wrd)        /* try word  verification again */
  1249.    endif
  1250.    if not (result or abbrev('FORCE', upcase(arg(3)), 1)) then    -- was it a success
  1251.       --.messageline='word is spelled correctly'
  1252.       return -2
  1253.    endif
  1254.    proof_word = wrd
  1255.    if proofdlg_hwnd then  -- Dialog started
  1256.       'proofdlg' proofdlg_hwnd 'newword'
  1257.    else
  1258.       sayerror 0        -- (Clear a "Spell checking..." message, if one was up.)
  1259.       'proofdlg pop'    -- Start the dialog; it will do the rest
  1260.    endif
  1261.    return -3
  1262.  
  1263.  
  1264. defc proofdlg
  1265.    universal ADDENDA_FILENAME
  1266.    universal proofdlg_hwnd, proof_word, proofdlg_whatflag, proof_offst, proof_resultofs, proof_prev_col
  1267. ;; universal proof_nextcol  -- temp
  1268.    parse arg hndle opt rest
  1269.    continue = 0
  1270.    if arg(1)='pop' then
  1271.  compile if E_DLL = 'UTKE600'
  1272.       call windowmessage(0,  getpminfo(EPMINFO_OWNERCLIENT),
  1273.                          5549,    --WM_USER + 0x0500 + 0x00AD = OBJEPM_PROOFDLG
  1274.                          0,
  1275.                          0)
  1276.  compile else
  1277.       call windowmessage(0,  getpminfo(APP_HANDLE),
  1278.                         5150,               -- EPM_POPPROOFDLG
  1279.                         0,
  1280.                         0)
  1281.  compile endif -- E_DLL = 'UTKE600'
  1282.    elseif opt='init' then
  1283.       if proofdlg_whatflag = 1 then
  1284.          msg = 'Proofing file'\0
  1285.       elseif proofdlg_whatflag = 2 then
  1286.          msg = 'Proofing marked area'\0
  1287.       elseif proofdlg_whatflag = 3 | proofdlg_whatflag = 4 then
  1288.          msg = 'Proofing word'\0
  1289.       else
  1290.          return
  1291.       endif
  1292.       call windowmessage(1,  hndle,   -- send message back to dialog
  1293.                          32,               -- WM_COMMAND - 0x0020
  1294.                          9193,             -- Set dialog title
  1295.                          ltoa(offset(msg) || selector(msg), 10) )
  1296.       proofdlg_hwnd = hndle
  1297.       if proof_word<>'' then
  1298.          'proofdlg' proofdlg_hwnd 'newword'
  1299.       endif
  1300.    elseif opt='newword' then
  1301.       if proof_word<>'' then
  1302.          oldwordlen=length(proof_word)
  1303.          oldcol = .col; .col = .col + oldwordlen; .col = oldcol;
  1304.          circleit PROOF_CIRCLE_STYLE, .line, .col, .col+oldwordlen-1, PROOF_CIRCLE_COLOR1, PROOF_CIRCLE_COLOR2
  1305. ;;       refresh  -- Refresh required to display circle, because control isn't being returned to the user
  1306.          msg = \26 proof_word\0  -- \26 is right arrow (also, EOF character!)
  1307.          call windowmessage(1,  proofdlg_hwnd,   -- send message back to dialog
  1308.                             32,               -- WM_COMMAND - 0x0020
  1309.                             9191,             -- Set current word being proofed
  1310.                             ltoa(offset(msg) || selector(msg), 10) )
  1311.       endif
  1312.       -- The following must be here, because 9191 re-enables the buttons.
  1313.       if proofdlg_whatflag = 3 | proofdlg_whatflag = 4 then
  1314.          call windowmessage(1,  proofdlg_hwnd,   -- send message back to dialog
  1315.                             32,               -- WM_COMMAND - 0x0020
  1316.                             9195,             -- Disable buttons
  1317.                             7+proofdlg_whatflag )  -- 10 or 11; Temp. Add, Next, and for whatflg=4, Replace
  1318.       endif
  1319.    elseif opt='suggest' then
  1320.        oldwordlen=length(proof_word)
  1321.        circleit PROOF_CIRCLE_STYLE, .line, .col, .col+oldwordlen-1, PROOF_CIRCLE_COLOR1, PROOF_CIRCLE_COLOR2
  1322.        parse value lexam(LXFSPAID, proof_word) with 2 '/' result
  1323.        if rc>=LXRFINIT then
  1324.           msg = LOOKUP_FAILED__MSG '<' proof_word '> RC='rc\0
  1325.           call windowmessage(1,  hndle,   -- send message back to dialog
  1326.                              32,               -- WM_COMMAND - 0x0020
  1327.                              9190,             -- Set dialog prompt
  1328.                              ltoa(offset(msg) || selector(msg), 10) )
  1329.        elseif result='' then
  1330.           msg = 'Nothing found for <' proof_word '>'\0
  1331.           call windowmessage(1,  hndle,   -- send message back to dialog
  1332.                              32,               -- WM_COMMAND - 0x0020
  1333.                              9190,             -- Set dialog prompt
  1334.                              ltoa(offset(msg) || selector(msg), 10) )
  1335.        else
  1336.           msg = result\0
  1337.           call windowmessage(1,  hndle,   -- send message back to dialog
  1338.                              32,               -- WM_COMMAND - 0x0020
  1339.                              9192,             -- Fill listbox
  1340.                              ltoa(offset(msg) || selector(msg), 10) )
  1341.        endif
  1342.    elseif opt='rep_l' | opt='rep_n' then  -- Replace from list / Replace with new word
  1343.       if proofdlg_whatflag <> 4 then  -- Shouldn't be, since we disable the button...
  1344. compile if 0  -- The following loses attributes.
  1345.          getline line
  1346.          replaceline leftstr(line,.col-1) || rest || substr(line,.col+length(proof_word))
  1347. compile else  -- A Change command will preserve them.
  1348.          getsearch oldsearch
  1349.          'xcom c '\1 || proof_word || \1 || rest || \1
  1350.          setsearch oldsearch
  1351. compile endif
  1352.       endif
  1353.       continue = 1
  1354.       if proofdlg_whatflag < 3 then
  1355.          proof_offst = proof_offst + length(rest) - length(proof_word)
  1356.          if opt='rep_n' then  -- Replace from list / Replace with new word
  1357.             proof_resultofs = proof_resultofs - 2  -- back up one word (recheck replaced word)
  1358.             proof_prev_col = .col
  1359. ;; proof_nextcol = .col
  1360.          endif
  1361.       endif
  1362.    elseif opt='add' then
  1363.       call AMU_addenda_addition_processing(proof_word)
  1364.       continue = 1
  1365.    elseif opt='tempadd' then
  1366.  compile if RESPECT_CASE_FOR_ADDENDA
  1367.       call lexam(LXFAD2TRS, proof_word)
  1368.  compile else
  1369.       call lexam(LXFAD2TRS,lowcase(proof_word))
  1370.  compile endif
  1371.       continue = 1
  1372.    elseif opt='next' then
  1373.       continue = 1
  1374.    elseif opt='close' then
  1375.       if addenda_filename<>'' then
  1376.          call maybe_save_addenda()
  1377.       endif
  1378.       call drop_dictionary()
  1379.       proofdlg_hwnd = ''
  1380.    else
  1381.       sayerror 'ProofDlg' arg(1)
  1382.    endif
  1383. ;sayerror 'proofdlg "'arg(1)'", continue =' continue
  1384.    if continue then  -- Continue to next word
  1385. ;;    .col = proof_nextcol
  1386.       if proofdlg_whatflag >= 3 then  -- We were proofing a single word; all done!
  1387.          call windowmessage(0,  hndle,           -- send message to dialog
  1388.                             41,                  -- WM_CLOSE - 0x0029
  1389.                             0,
  1390.                             0)
  1391.       else  -- really have to keep going
  1392.           call windowmessage(1,  hndle,   -- send message back to dialog
  1393.                              32,               -- WM_COMMAND - 0x0020
  1394.                              9194,             -- Disable everything
  1395.                              0)
  1396.          if opt<>'rep_n' then
  1397.             proof_prev_col = ''
  1398.          endif
  1399.          'keep_on_prufin'
  1400.       endif
  1401.    endif
  1402. compile endif  -- USE_CUSTOM_PROOF_DIALOG
  1403.  
  1404. const SPELL_DEBUG = 0
  1405.  
  1406. defkeys spell_keys overlay  -- For dynamic spell-checking
  1407.  
  1408. def space, enter =
  1409.    universal EPM_utility_array_ID
  1410.    universal dynaspel_line, dynaspel_col
  1411.    getline line
  1412.    saveline = .line
  1413.    savecol = .col - 1
  1414.    getfileid fid
  1415.    do_array 3, EPM_utility_array_ID, 'dspl.'fid, xkeyset  -- Restore original keyset for this fileid.
  1416.    .keyset = xkeyset
  1417.    executekey lastkey()
  1418.    keys spell_keys
  1419.    if not savecol or line = '' then
  1420. compile if SPELL_DEBUG
  1421.       sayerror '[Line was blank]'
  1422. compile endif -- DEBUG
  1423.       return
  1424.    endif
  1425.    if substr(line, savecol, 1) = ' ' then
  1426. compile if SPELL_DEBUG
  1427.       sayerror '[Prev. char was blank]'
  1428. compile endif -- DEBUG
  1429.       return
  1430.    endif
  1431. ;  newcol = .col
  1432.    start = lastpos(' ', line, savecol)
  1433.    wrd = substr(line, start+1, savecol - start)
  1434.    if not verify(wrd, LEXAM_PUNCTUATION) then  -- No letters in "word"; skip it.
  1435. compile if SPELL_DEBUG
  1436.       sayerror '[Only punctuation in word 'wrd']'
  1437. compile endif -- DEBUG
  1438.       return
  1439.    endif
  1440.    result=lexam(LXFVERFY,wrd)          /* authenticate word using lexam */
  1441.    if result then
  1442.       call strippunct(wrd,savecol,tmp)
  1443.       result = lexam(LXFVERFY,wrd)
  1444.    endif
  1445.    if(result <> LXRFGOOD) then         /* was it a success ???          */
  1446.       call beep(1000, 100)
  1447.       dynaspel_line = saveline
  1448.       dynaspel_col = savecol
  1449.       sayerror 'Unknown word was 'wrd' - press Ctrl+A for alternates.'
  1450. compile if SPELL_DEBUG
  1451.    else
  1452.       sayerror '[Word was 'wrd' - OK]'
  1453. compile endif -- DEBUG
  1454.    endif
  1455.  
  1456. def c_A =
  1457.    universal dynaspel_line, dynaspel_col
  1458.    if not dynaspel_line then
  1459.       sayerror 'No misspelled word remembered.'
  1460.       return
  1461.    endif
  1462.    if .line=dynaspel_line then
  1463.       oldlen = length(textline(dynaspel_line))
  1464.    endif
  1465.    call psave_pos(save_pos)
  1466.    dynaspel_line; .col = dynaspel_col
  1467.    'proofword'
  1468. compile if not USE_CUSTOM_PROOF_DIALOG
  1469.    call prestore_pos(save_pos)
  1470.    if .line=dynaspel_line then
  1471.       diff = length(textline(dynaspel_line)) - oldlen
  1472.       if diff>0 then
  1473.          right diff
  1474.       elseif diff<0 then
  1475.          left diff
  1476.       endif
  1477.    endif
  1478. compile endif
  1479.  
  1480.  
  1481. defc dynaspell =  -- Takes no arguments; just toggles setting.
  1482.    universal EPM_utility_array_ID
  1483.    universal ADDENDA_FILENAME
  1484.    getfileid fid
  1485.    if .keyset<>'SPELL_KEYS' then  -- Dynamic spell-checking off for this file
  1486.       if load_lexam() then
  1487.          return
  1488.       endif
  1489.       tmp_keyset = .keyset
  1490.       do_array 2, EPM_utility_array_ID, 'dspl.'fid, tmp_keyset  -- Remember original keyset for this fileid.
  1491.       keys spell_keys
  1492.    else  -- Dynamic spell-checking is on; now being turned off.
  1493. compile if ADDENDASUPPORT
  1494.       if addenda_filename<>'' then
  1495.          call maybe_save_addenda()
  1496.       endif
  1497. compile endif
  1498.       call drop_dictionary()
  1499.       do_array 3, EPM_utility_array_ID, 'dspl.'fid, tmp_keyset  -- Remember original keyset for this fileid.
  1500.       .keyset = tmp_keyset
  1501.       empty = ''
  1502.       do_array 2, EPM_utility_array_ID, 'dspl.'fid, empty
  1503.    endif
  1504.