comparison lisp/textmodes/ispell.el @ 27260:ec1a21729421

(xemacsp, version18p, version-20p): Add ispell- prefix. Only define dictionaries in menus when they exist. (version18p): New variable. (version20p): New variable. (xemacsp): New variable. (ispell-choices-win-default-height): Fix for XEmacs visibility. (ispell-dictionary-alist1): Added Brasileiro dictionary. (ispell-dictionary-alist6): Russian command lines no longer accept run-together words. (ispell-local-dictionary-alist): Add koi8-r to customize definition. (ispell-dictionary-alist): Add koi8-r to customize definition. (check-ispell-version): Added documentation string. Returns library path when called non-interactively. (ispell-menu-map-needed): Uses new variables. (ispell-library-path): New variable. (ispell-decode-string): XEmacs fix for bogus variable bindings. (ispell-word): Improved documentation string. Test for valid character mappings. Correctly check typed in word changes that can result in single words split into multiple words. Returns replacement word. (ispell-command-loop): Fixes XEmacs display bugs. Show word to replace in recursive query replace mode. Help message for recursive edit mode. (ispell-show-choices): Protect against bad framepop bindings. (ispell-help): Fix to work with XEmacs. (ispell-highlight-spelling-error): Use new variables. (ispell-overlay-window): Fix to work with XEmacs. (ispell-parse-output): Passed and returns location information tracking spelling corrections. Doesn't recheck same word on current line. (ispell-init-process): Protect against bogus XEmacs variable binding. Fix call to single argument in sleep-for. Use new variables. (ispell-region): Passed and returns location information tracking spelling corrections. Doesn't check same word on current line. Improved documentation string. Doesn't resend a line already checked to the ispell process - fixes bug in LaTeX parsing. (ispell-begin-skip-region-regexp): No longer skips <TT> in SGML. (ispell-skip-region): No longer skips <TT> in SGML. (ispell-process-line): Tracks location information with spelling corrections. Added documentation string. Accounts for words already accepted on this line. Don't allow query-replace on line starting with math characters. Doesn't resend a line already sent to ispell process. Fixes alignment error bug.
author Gerd Moellmann <gerd@gnu.org>
date Mon, 10 Jan 2000 12:02:49 +0000
parents 2439fc8b756c
children 7d8ea470609b
comparison
equal deleted inserted replaced
27259:c41efa6c4be1 27260:ec1a21729421
1 ;;; ispell.el --- Interface to International Ispell Version 3.1 1 ;;; ispell.el --- Interface to International Ispell Versions 3.1 and 3.2
2 2
3 ;; Copyright (C) 1994, 1995, 1997, 1998, 1999 Free Software Foundation, Inc. 3 ;; Copyright (C) 1994, 1995, 1997, 1998, 1999 Free Software Foundation, Inc.
4 4
5 ;; Authors : Ken Stevens <k.stevens@ieee.org> 5 ;; Authors : Ken Stevens <k.stevens@ieee.org>
6 ;; Stevens Mod Date: Fri May 7 14:25:14 PDT 1999 6 ;; Stevens Mod Date: Mon 29 Nov 11:38:34 PST 1999
7 ;; Stevens Revision: 3.2 7 ;; Stevens Revision: 3.3
8 ;; Status : Release with 3.1.12+ ispell. 8 ;; Status : Release with 3.1.12+ and 3.2.0+ ispell.
9 ;; Bug Reports : ispell-el-bugs@itcorp.com 9 ;; Bug Reports : ispell-el-bugs@itcorp.com
10 ;; Web Site : http://kdstevens.com/~stevens/ispell-page.html 10 ;; Web Site : http://kdstevens.com/~stevens/ispell-page.html
11 11
12 ;; This file is part of GNU Emacs. 12 ;; This file is part of GNU Emacs.
13 13
112 ;; spell check in `ispell-skip-region-alist'. Mode-dependent features can 112 ;; spell check in `ispell-skip-region-alist'. Mode-dependent features can
113 ;; be added to latex by modifying `ispell-tex-skip-alists'. 113 ;; be added to latex by modifying `ispell-tex-skip-alists'.
114 ;; `ispell-message' contains some custom skipping code for e-mail messages. 114 ;; `ispell-message' contains some custom skipping code for e-mail messages.
115 115
116 ;; BUGS: 116 ;; BUGS:
117 ;; Accepting word definitions in latex mode can mess up math mode skipping. 117 ;; Need a way to select between different character mappings without separate
118 ;; dictionary entries.
119 ;; Multi-byte characters if not defined by current dictionary may result in the
120 ;; evil "misalignment error" in some versions of MULE emacs.
118 ;; On some versions of emacs, growing the minibuffer fails. 121 ;; On some versions of emacs, growing the minibuffer fails.
119 ;; see `ispell-help-in-bufferp'. 122 ;; see `ispell-help-in-bufferp'.
123 ;; Recursive edits (?C-r or ?R) inside a keyboard text replacement check (?r)
124 ;; can cause misalignment errors.
120 125
121 ;; HISTORY 126 ;; HISTORY
122 127
123 ;; Modifications made in latest versions: 128 ;; Modifications made in latest versions:
129
130 ;; Revision 3.3 1999/11/29 11:38:34 kss
131 ;; Only word replacements entered in from the keyboard are rechecked.
132 ;; This fixes a bug in tex parsing and misalignment.
133 ;; Exceptions exist for recursive edit and query-replace, with tex error
134 ;; condition tested. Recursive editing improved.
135 ;; XEmacs repair for when `enable-multibyte-characters' defined - Didier Verna.
136 ;; ispell-help fixed for XEmacs. Choices minibuffer now displayed in XEmacs.
137 ;; Only list valid dictionaries in Spell menu. Russian dictionary doesn't allow
138 ;; run-together words, and uses koi8-r font. Don't skip text in html <TT>
139 ;; fonts.
124 140
125 ;; Revision 3.2 1999/5/7 14:25:14 kss 141 ;; Revision 3.2 1999/5/7 14:25:14 kss
126 ;; Accept ispell versions 3.X.Y where X>=1 142 ;; Accept ispell versions 3.X.Y where X>=1
127 ;; fine tuned latex region skipping. Fixed bug in ispell-word that did not 143 ;; fine tuned latex region skipping. Fixed bug in ispell-word that did not
128 ;; point in right place on words < 2 chars. Simplified ispell-minor-mode. 144 ;; point in right place on words < 2 chars. Simplified ispell-minor-mode.
143 ;; Robustness added to ensure `case-fold-search' doesn't get redefined. 159 ;; Robustness added to ensure `case-fold-search' doesn't get redefined.
144 ;; Fixed bug that didn't respect case of word in `ispell-complete-word'. 160 ;; Fixed bug that didn't respect case of word in `ispell-complete-word'.
145 ;; Multibyte character coding support added for process interactions. 161 ;; Multibyte character coding support added for process interactions.
146 ;; Ensure ispell process has terminated before starting new process. 162 ;; Ensure ispell process has terminated before starting new process.
147 ;; This can otherwise confuse process filters and hang ispell. 163 ;; This can otherwise confuse process filters and hang ispell.
148 ;; Improved skipping support for sgml. 164 ;; Improved skipping support for SGML.
149 ;; Fixed bug using ^M rather than \r in `ispell-minor-check'. 165 ;; Fixed bug using ^M rather than \r in `ispell-minor-check'.
150 ;; Improved message reference matching in `ispell-message'. 166 ;; Improved message reference matching in `ispell-message'.
151 ;; Fixed bug in returning to nroff mode from tex mode. 167 ;; Fixed bug in returning to nroff mode from tex mode.
152 168
153 169
164 (eval-when-compile 180 (eval-when-compile
165 (if (fboundp 'defgroup) 181 (if (fboundp 'defgroup)
166 (defgroup ispell nil 182 (defgroup ispell nil
167 "User variables for emacs ispell interface." 183 "User variables for emacs ispell interface."
168 :group 'applications))) 184 :group 'applications)))
185
186
187 ;;;###autoload
188 (defconst ispell-xemacsp (string-match "Lucid\\|XEmacs" emacs-version)
189 "Non nil if using XEmacs.")
190
191 ;;;###autoload
192 (defconst ispell-version18p (string-match "18\\.[0-9]+\\.[0-9]+" emacs-version)
193 "Non nil if using emacs version 18.")
194
195 ;;;###autoload
196 (defconst ispell-version20p (string-match "20\\.[0-9]+\\.[0-9]+" emacs-version)
197 "Non nil if using emacs version 20.")
169 198
170 199
171 ;;; ********************************************************************** 200 ;;; **********************************************************************
172 ;;; The following variables should be set according to personal preference 201 ;;; The following variables should be set according to personal preference
173 ;;; and location of binaries: 202 ;;; and location of binaries:
227 "*When not nil, the `*Choices*' window remains for spelling session. 256 "*When not nil, the `*Choices*' window remains for spelling session.
228 This minimizes redisplay thrashing." 257 This minimizes redisplay thrashing."
229 :type 'boolean 258 :type 'boolean
230 :group 'ispell) 259 :group 'ispell)
231 260
232 (defcustom ispell-choices-win-default-height 2 261 (defcustom ispell-choices-win-default-height (if ispell-xemacsp 3 2)
233 "*The default size of the `*Choices*' window, including status line. 262 "*The default size of the `*Choices*' window, including mode line.
234 Must be greater than 1." 263 Must be greater than 1.
264 XEmacs modeline is thicker than a line of text, so it partially covers the
265 last line of text in the buffer. Include an extra line in XEmacs to see
266 all of the choices clearly."
235 :type 'integer 267 :type 'integer
236 :group 'ispell) 268 :group 'ispell)
237 269
238 (defcustom ispell-program-name "ispell" 270 (defcustom ispell-program-name "ispell"
239 "Program invoked by \\[ispell-word] and \\[ispell-region] commands." 271 "Program invoked by \\[ispell-word] and \\[ispell-region] commands."
395 for language-specific arguments." 427 for language-specific arguments."
396 :type '(repeat string) 428 :type '(repeat string)
397 :group 'ispell) 429 :group 'ispell)
398 430
399 431
400 ;; Define definitions here only for personal dictionaries. 432 ;;; Define definitions here only for personal dictionaries.
401 ;;;###autoload 433 ;;;###autoload
402 (defcustom ispell-local-dictionary-alist nil 434 (defcustom ispell-local-dictionary-alist nil
403 "*Contains local or customized dictionary definitions. 435 "*Contains local or customized dictionary definitions.
404 See `ispell-dictionary-alist'." 436 See `ispell-dictionary-alist'."
405 :type '(repeat (list (choice :tag "Dictionary" 437 :type '(repeat (list (choice :tag "Dictionary"
431 ispell-dictionary-alist-1 463 ispell-dictionary-alist-1
432 '((nil ; default (English.aff) 464 '((nil ; default (English.aff)
433 "[A-Za-z]" "[^A-Za-z]" "[']" nil ("-B") nil iso-8859-1) 465 "[A-Za-z]" "[^A-Za-z]" "[']" nil ("-B") nil iso-8859-1)
434 ("american" ; Yankee English 466 ("american" ; Yankee English
435 "[A-Za-z]" "[^A-Za-z]" "[']" nil ("-B") nil iso-8859-1) 467 "[A-Za-z]" "[^A-Za-z]" "[']" nil ("-B") nil iso-8859-1)
468 ("brasiliano" ; Brazilian mode
469 "[A-Z\301\311\315\323\332\300\310\314\322\331\303\325\307\334\302\312\324a-z\341\351\355\363\372\340\350\354\362\371\343\365\347\374\342\352\364]"
470 "[^A-Z\301\311\315\323\332\300\310\314\322\331\303\325\307\334\302\312\324a-z\341\351\355\363\372\340\350\354\362\371\343\365\347\374\342\352\364]"
471 "[']" nil ("-d" "brasileiro") nil iso-8859-1)
436 ("british" ; British version 472 ("british" ; British version
437 "[A-Za-z]" "[^A-Za-z]" "[']" nil ("-B" "-d" "british") nil iso-8859-1) 473 "[A-Za-z]" "[^A-Za-z]" "[']" nil ("-B" "-d" "british") nil iso-8859-1)
438 ("castellano" ; Spanish mode 474 ("castellano" ; Spanish mode
439 "[A-Z\301\311\315\321\323\332\334a-z\341\351\355\361\363\372\374]" 475 "[A-Z\301\311\315\321\323\332\334a-z\341\351\355\361\363\372\374]"
440 "[^A-Z\301\311\315\321\323\332\334a-z\341\351\355\361\363\372\374]" 476 "[^A-Z\301\311\315\321\323\332\334a-z\341\351\355\361\363\372\374]"
522 558
523 ;;; Sixth part of dictionary, shortened for loaddefs.el 559 ;;; Sixth part of dictionary, shortened for loaddefs.el
524 ;;;###autoload 560 ;;;###autoload
525 (setq 561 (setq
526 ispell-dictionary-alist-6 562 ispell-dictionary-alist-6
563 ;; include Russian iso character set too?
564 ;; "[']" t ("-d" "russian") "~latin1" iso-8859-1
527 '(("russian" ; Russian.aff (KOI8-R charset) 565 '(("russian" ; Russian.aff (KOI8-R charset)
528 "[\341\342\367\347\344\345\263\366\372\351\352\353\354\355\356\357\360\362\363\364\365\346\350\343\376\373\375\370\371\377\374\340\361\301\302\327\307\304\305\243\326\332\311\312\313\314\315\316\317\320\322\323\324\325\306\310\303\336\333\335\330\331\337\334\300\321]" 566 "[\341\342\367\347\344\345\263\366\372\351\352\353\354\355\356\357\360\362\363\364\365\346\350\343\376\373\375\370\371\377\374\340\361\301\302\327\307\304\305\243\326\332\311\312\313\314\315\316\317\320\322\323\324\325\306\310\303\336\333\335\330\331\337\334\300\321]"
529 "[^\341\342\367\347\344\345\263\366\372\351\352\353\354\355\356\357\360\362\363\364\365\346\350\343\376\373\375\370\371\377\374\340\361\301\302\327\307\304\305\243\326\332\311\312\313\314\315\316\317\320\322\323\324\325\306\310\303\336\333\335\330\331\337\334\300\321]" 567 "[^\341\342\367\347\344\345\263\366\372\351\352\353\354\355\356\357\360\362\363\364\365\346\350\343\376\373\375\370\371\377\374\340\361\301\302\327\307\304\305\243\326\332\311\312\313\314\315\316\317\320\322\323\324\325\306\310\303\336\333\335\330\331\337\334\300\321]"
530 "" nil ("-d" "russian") nil koi8-r) 568 "" nil ("-d" "russian") nil koi8-r)
531 ("svenska" ; Swedish mode 569 ("svenska" ; Swedish mode
616 654
617 ;;; The preparation of the menu bar menu must be autoloaded 655 ;;; The preparation of the menu bar menu must be autoloaded
618 ;;; because otherwise this file gets autoloaded every time Emacs starts 656 ;;; because otherwise this file gets autoloaded every time Emacs starts
619 ;;; so that it can set up the menus and determine keyboard equivalents. 657 ;;; so that it can set up the menus and determine keyboard equivalents.
620 658
659
660 ;;; The version must be 3.1 or greater for this version of ispell.el
661 ;;; There is an incompatibility between version 3.1.12 and lower versions.
662 (defconst ispell-required-version '(3 1 12)
663 "Ispell versions with which this version of ispell.el is known to work.")
664 (defvar ispell-offset -1
665 "Offset that maps protocol differences between ispell 3.1 versions.")
666
667 (defconst ispell-version "ispell.el 3.3 -- Mon 29 Nov 11:38:34 PST 1999")
668
669
670 (defun check-ispell-version (&optional interactivep)
671 "Ensure that `ispell-program-name' is valid and the correct version.
672 Returns version number if called interactively.
673 Otherwise returns the library path if defined."
674 ;; This is a little wasteful as we actually launch ispell twice: once
675 ;; to make sure it's the right version, and once for real. But people
676 ;; get confused by version mismatches *all* the time (and I've got the
677 ;; email to prove it) so I think this is worthwhile. And the -v[ersion]
678 ;; option is the only way I can think of to do this that works with
679 ;; all versions, since versions earlier than 3.0.09 didn't identify
680 ;; themselves on startup.
681 (interactive "p")
682 (let ((case-fold-search-val case-fold-search)
683 ;; avoid bugs when syntax of `.' changes in various default modes
684 (default-major-mode 'fundamental-mode)
685 result status)
686 (save-excursion
687 (set-buffer (get-buffer-create " *ispell-tmp*"))
688 (erase-buffer)
689 (setq status (call-process ispell-program-name nil t nil "-vv"))
690 (goto-char (point-min))
691 (if interactivep
692 (progn
693 (end-of-line)
694 (setq result (concat (buffer-substring-no-properties (point-min)
695 (point))
696 ", "
697 ispell-version))
698 (message result))
699 ;; return library path.
700 (re-search-forward "LIBDIR = \\\"\\([^ \t\n]*\\)\\\"" nil t)
701 (if (match-beginning 0)
702 (setq result (buffer-substring (match-beginning 1) (match-end 1)))))
703 (goto-char (point-min))
704 (if (not (memq status '(0 nil)))
705 (error "%s exited with %s %s" ispell-program-name
706 (if (stringp status) "signal" "code") status))
707 (setq case-fold-search t
708 status (re-search-forward
709 (concat "\\<\\("
710 (format "%d" (car ispell-required-version))
711 "\\)\\.\\([0-9]*\\)\\.\\([0-9]*\\)\\>")
712 nil t)
713 case-fold-search case-fold-search-val)
714 (if (or (not status) ; major version mismatch
715 (< (car (read-from-string (buffer-substring-no-properties
716 (match-beginning 2) (match-end 2))))
717 (car (cdr ispell-required-version)))) ; minor version mismatch
718 (error "%s version 3 release %d.%d.%d or greater is required"
719 ispell-program-name (car ispell-required-version)
720 (car (cdr ispell-required-version))
721 (car (cdr (cdr ispell-required-version))))
722 ;; check that it is the correct version.
723 (if (and (= (car (read-from-string (buffer-substring-no-properties
724 (match-beginning 2)(match-end 2))))
725 (car (cdr ispell-required-version)))
726 (< (car (read-from-string (buffer-substring-no-properties
727 (match-beginning 3)(match-end 3))))
728 (car (cdr (cdr ispell-required-version)))))
729 (setq ispell-offset 0)))
730 (kill-buffer (current-buffer)))
731 result))
732
733
621 ;;;###autoload 734 ;;;###autoload
622 (defvar ispell-menu-map nil "Key map for ispell menu.") 735 (defvar ispell-menu-map nil "Key map for ispell menu.")
623 ;;; redo menu when loading ispell to get dictionary modifications 736 ;;; redo menu when loading ispell to get dictionary modifications
624 (setq ispell-menu-map nil) 737 (setq ispell-menu-map nil)
625 738
632 ;;; Break out XEmacs menu and split into several calls to avoid having 745 ;;; Break out XEmacs menu and split into several calls to avoid having
633 ;;; long lines in loaddefs.el. Detect need off following constant. 746 ;;; long lines in loaddefs.el. Detect need off following constant.
634 747
635 ;;; Set up dictionary 748 ;;; Set up dictionary
636 ;;;###autoload 749 ;;;###autoload
637 (defconst ispell-menu-map-needed 750 (defvar ispell-menu-map-needed
638 ;; only needed when not version 18 and not XEmacs. 751 ;; only needed when not version 18 and not XEmacs.
639 (and (not ispell-menu-map) 752 (and (not ispell-menu-map)
640 (not (string-match "18\\.[0-9]+\\.[0-9]+" emacs-version)) 753 (not ispell-version18p)
641 (not (string-match "Lucid\\|XEmacs" emacs-version)))) 754 (not ispell-xemacsp)
755 'reload))
756
757 (defvar ispell-library-path (check-ispell-version)
758 "The directory where ispell dictionaries reside.")
759
642 760
643 ;;;###autoload 761 ;;;###autoload
644 (if ispell-menu-map-needed 762 (if ispell-menu-map-needed
645 (let ((dicts (reverse (cons (cons "default" nil) ispell-dictionary-alist))) 763 (let ((dicts (reverse (cons (cons "default" nil) ispell-dictionary-alist)))
646 name) 764 ;; `ispell-library-path' intentionally not defined in autoload
765 (path (and (boundp 'ispell-library-path) ispell-library-path))
766 name load-dict)
647 (setq ispell-menu-map (make-sparse-keymap "Spell")) 767 (setq ispell-menu-map (make-sparse-keymap "Spell"))
648 ;; add the dictionaries to the bottom of the list. 768 ;; add the dictionaries to the bottom of the list.
649 (while dicts 769 (while dicts
650 (setq name (car (car dicts)) 770 (setq name (car (car dicts))
771 load-dict (car (cdr (member "-d" (nth 5 (car dicts)))))
651 dicts (cdr dicts)) 772 dicts (cdr dicts))
652 (if (stringp name) 773 (cond ((not (stringp name))
653 (define-key ispell-menu-map (vector (intern name)) 774 (define-key ispell-menu-map (vector 'default)
654 (cons (concat "Select " (capitalize name)) 775 (cons "Select Default Dict"
655 (list 'lambda () '(interactive) 776 (list 'lambda () '(interactive)
656 (list 'ispell-change-dictionary name)))))))) 777 (list 'ispell-change-dictionary "default")))))
778 ((or (not path) ; load all if library dir not defined
779 (file-exists-p (concat path "/" name ".hash"))
780 (file-exists-p (concat path "/" name ".has"))
781 (and load-dict
782 (or (file-exists-p(concat path "/" load-dict ".hash"))
783 (file-exists-p(concat path "/" load-dict ".has")))))
784 (define-key ispell-menu-map (vector (intern name))
785 (cons (concat "Select " (capitalize name))
786 (list 'lambda () '(interactive)
787 (list 'ispell-change-dictionary name)))))))))
788
657 789
658 ;;; define commands in menu in opposite order you want them to appear. 790 ;;; define commands in menu in opposite order you want them to appear.
659 ;;;###autoload 791 ;;;###autoload
660 (if ispell-menu-map-needed 792 (if ispell-menu-map-needed
661 (progn 793 (progn
693 ;; use (x-popup-menu last-nonmenu-event(list "" ispell-help-list)) ? 825 ;; use (x-popup-menu last-nonmenu-event(list "" ispell-help-list)) ?
694 '("Help" . (lambda () (interactive) (describe-function 'ispell-help)))) 826 '("Help" . (lambda () (interactive) (describe-function 'ispell-help))))
695 (put 'ispell-region 'menu-enable 'mark-active) 827 (put 'ispell-region 'menu-enable 'mark-active)
696 (fset 'ispell-menu-map (symbol-value 'ispell-menu-map)))) 828 (fset 'ispell-menu-map (symbol-value 'ispell-menu-map))))
697 829
698 ;;; XEmacs version 19 & 20 830 ;;; XEmacs versions 19 & 20
699 (if (and (not (string-match "18\\.[0-9]+\\.[0-9]+" emacs-version)) 831 (if (and ispell-xemacsp
700 (string-match "Lucid\\|XEmacs" emacs-version) 832 (not ispell-version18p)
701 (featurep 'menubar) 833 (featurep 'menubar)
702 (null ispell-menu-xemacs) 834 (null ispell-menu-xemacs)
703 (not (and (boundp 'infodock-version) infodock-version))) 835 (not (and (boundp 'infodock-version) infodock-version)))
704 (let ((dicts (cons (cons "default" nil) ispell-dictionary-alist)) 836 (let ((dicts (cons (cons "default" nil) ispell-dictionary-alist))
705 (current-menubar (or current-menubar default-menubar)) 837 (current-menubar (or current-menubar default-menubar))
714 ["Continue Check" ispell-continue t] 846 ["Continue Check" ispell-continue t]
715 ["Complete Word Frag"ispell-complete-word-interior-frag t] 847 ["Complete Word Frag"ispell-complete-word-interior-frag t]
716 ["Complete Word" ispell-complete-word t] 848 ["Complete Word" ispell-complete-word t]
717 ["Kill Process" ispell-kill-ispell t] 849 ["Kill Process" ispell-kill-ispell t]
718 "-" 850 "-"
719 ["Save Dictionary" (ispell-pdict-save t t) t] 851 ["Save Personal Dict"(ispell-pdict-save t t) t]
720 ["Change Dictionary" ispell-change-dictionary t])) 852 ["Change Dictionary" ispell-change-dictionary t]
721 name) 853 ["Select Default" (ispell-change-dictionary "default") t]))
854 name load-dict)
722 (while dicts 855 (while dicts
723 (setq name (car (car dicts)) 856 (setq name (car (car dicts))
857 load-dict (car (cdr (member "-d" (nth 5 (car dicts)))))
724 dicts (cdr dicts)) 858 dicts (cdr dicts))
725 (if (stringp name) 859 ;; Include if the dictionary is in the library, or path not defined.
860 (if (and (stringp name)
861 (or (not ispell-library-path)
862 (file-exists-p (concat ispell-library-path "/"
863 name ".hash"))
864 (file-exists-p (concat ispell-library-path "/"
865 name ".has"))
866 (and load-dict
867 (or (file-exists-p (concat ispell-library-path "/"
868 load-dict ".hash"))
869 (file-exists-p (concat ispell-library-path "/"
870 load-dict ".has"))))))
726 (setq menu (append menu 871 (setq menu (append menu
727 (list 872 (list
728 (vector (concat "Select " (capitalize name)) 873 (vector (concat "Select " (capitalize name))
729 (list 'ispell-change-dictionary name) 874 (list 'ispell-change-dictionary name)
730 t)))))) 875 t))))))
733 (progn 878 (progn
734 (delete-menu-item '("Edit" "Spell")) ; in case already defined 879 (delete-menu-item '("Edit" "Spell")) ; in case already defined
735 (add-menu '("Edit") "Spell" ispell-menu-xemacs))))) 880 (add-menu '("Edit") "Spell" ispell-menu-xemacs)))))
736 881
737 ;;; Allow incrementing characters as integers in XEmacs 20 882 ;;; Allow incrementing characters as integers in XEmacs 20
738 (if (and (string-match "XEmacs" emacs-version) 883 (if (and ispell-xemacsp
739 (fboundp 'int-char)) 884 (fboundp 'int-char))
740 (fset 'ispell-int-char 'int-char) 885 (fset 'ispell-int-char 'int-char)
741 ;; Emacs and XEmacs 19 or earlier 886 ;; Emacs and XEmacs 19 or earlier
742 (fset 'ispell-int-char 'identity)) 887 (fset 'ispell-int-char 'identity))
743 888
744 889
745 ;;; ********************************************************************** 890 ;;; **********************************************************************
746 ;;; The following are used by ispell, and should not be changed. 891 ;;; The following are used by ispell, and should not be changed.
747 ;;; ********************************************************************** 892 ;;; **********************************************************************
748 893
749
750 ;;; The version must be 3.1 or greater for this version of ispell.el
751 ;;; There is an incompatibility between version 3.1.12 and lower versions.
752 (defconst ispell-required-version '(3 1 12)
753 "Ispell versions with which this version of ispell.el is known to work.")
754 (defvar ispell-offset -1
755 "Offset that maps protocol differences between ispell 3.1 versions.")
756 894
757 ;;; This variable contains the current dictionary being used if the ispell 895 ;;; This variable contains the current dictionary being used if the ispell
758 ;;; process is running. Otherwise it contains the global default. 896 ;;; process is running. Otherwise it contains the global default.
759 (defvar ispell-dictionary nil 897 (defvar ispell-dictionary nil
760 "The name of the current dictionary, or nil for the default. 898 "The name of the current dictionary, or nil for the default.
763 901
764 This is passed to the ispell process using the `-d' switch and is 902 This is passed to the ispell process using the `-d' switch and is
765 used as key in `ispell-dictionary-alist' (which see).") 903 used as key in `ispell-dictionary-alist' (which see).")
766 904
767 (defun ispell-decode-string (str) 905 (defun ispell-decode-string (str)
768 "Decodes multibyte character strings." 906 "Decodes multibyte character strings.
769 (if (and (boundp 'enable-multibyte-characters) 907 Protects against bogus binding of `enable-multibyte-characters' in XEmacs."
908 (if (and (or ispell-xemacsp
909 (and (boundp 'enable-multibyte-characters)
910 enable-multibyte-characters))
770 (fboundp 'decode-coding-string) 911 (fboundp 'decode-coding-string)
771 enable-multibyte-characters
772 (ispell-get-coding-system)) 912 (ispell-get-coding-system))
773 (decode-coding-string str (ispell-get-coding-system)) 913 (decode-coding-string str (ispell-get-coding-system))
774 str)) 914 str))
775 915
776 (defun ispell-get-casechars () 916 (defun ispell-get-casechars ()
953 ;;; ********************************************************************** 1093 ;;; **********************************************************************
954 ;;; ********************************************************************** 1094 ;;; **********************************************************************
955 1095
956 1096
957 1097
958 (and (not (string-match "18\\.[0-9]+\\.[0-9]+" emacs-version)) 1098 (and (not ispell-version18p)
959 (not (boundp 'epoch::version)) 1099 (not (boundp 'epoch::version))
960 (defalias 'ispell 'ispell-buffer) 1100 (defalias 'ispell 'ispell-buffer)
961 (defalias 'ispell-check-version 'check-ispell-version)) 1101 (defalias 'ispell-check-version 'check-ispell-version))
962 1102
963 1103
984 resume interrupted spell-checking of a buffer or region. 1124 resume interrupted spell-checking of a buffer or region.
985 1125
986 Word syntax described by `ispell-dictionary-alist' (which see). 1126 Word syntax described by `ispell-dictionary-alist' (which see).
987 1127
988 This will check or reload the dictionary. Use \\[ispell-change-dictionary] 1128 This will check or reload the dictionary. Use \\[ispell-change-dictionary]
989 or \\[ispell-region] to update the Ispell process." 1129 or \\[ispell-region] to update the Ispell process.
1130
1131 return values:
1132 nil word is correct or spelling is accpeted.
1133 0 word is inserted into buffer-local definitions.
1134 \"word\" word corrected from word list.
1135 \(\"word\" arg\) word is hand entered.
1136 quit spell session exited."
1137
990 (interactive (list nil nil current-prefix-arg)) 1138 (interactive (list nil nil current-prefix-arg))
991 (if continue 1139 (if continue
992 (ispell-continue) 1140 (ispell-continue)
993 (if (interactive-p) 1141 (if (interactive-p)
994 (setq following ispell-following-word 1142 (setq following ispell-following-word
1014 (while (progn 1162 (while (progn
1015 (accept-process-output ispell-process) 1163 (accept-process-output ispell-process)
1016 (not (string= "" (car ispell-filter))))) 1164 (not (string= "" (car ispell-filter)))))
1017 ;;(process-send-string ispell-process "!\n") ;back to terse mode. 1165 ;;(process-send-string ispell-process "!\n") ;back to terse mode.
1018 (setq ispell-filter (cdr ispell-filter)) ; remove extra \n 1166 (setq ispell-filter (cdr ispell-filter)) ; remove extra \n
1019 (if (listp ispell-filter) 1167 (if (and ispell-filter (listp ispell-filter))
1020 (setq poss (ispell-parse-output (car ispell-filter)))) 1168 (if (> (length ispell-filter) 1)
1169 (error "Ispell and its process have different character maps.")
1170 (setq poss (ispell-parse-output (car ispell-filter)))))
1021 (cond ((eq poss t) 1171 (cond ((eq poss t)
1022 (or quietly 1172 (or quietly
1023 (message "%s is correct" 1173 (message "%s is correct"
1024 (funcall ispell-format-word word)))) 1174 (funcall ispell-format-word word))))
1025 ((stringp poss) 1175 ((stringp poss)
1052 (if (not (atom replace)) ;recheck spelling of replacement 1202 (if (not (atom replace)) ;recheck spelling of replacement
1053 (progn 1203 (progn
1054 (if (car (cdr replace)) ; query replace requested 1204 (if (car (cdr replace)) ; query replace requested
1055 (save-window-excursion 1205 (save-window-excursion
1056 (query-replace word new-word t))) 1206 (query-replace word new-word t)))
1057 (ispell-region start end))))) 1207 (goto-char start)
1208 ;; single word could be split into multiple words
1209 (setq ispell-quit (not (ispell-region start end)))
1210 ))))
1211 ;; keep if rechecking word and we keep choices win.
1058 (if (get-buffer ispell-choices-buffer) 1212 (if (get-buffer ispell-choices-buffer)
1059 (kill-buffer ispell-choices-buffer)))) 1213 (kill-buffer ispell-choices-buffer))))
1060 (ispell-pdict-save ispell-silently-savep) 1214 (ispell-pdict-save ispell-silently-savep)
1061 (if ispell-quit (setq ispell-quit nil)))) 1215 ;; NB: Cancels ispell-quit incorrectly if called from ispell-region
1062 (goto-char cursor-location)))) ; return to original location 1216 (if ispell-quit (setq ispell-quit nil replace 'quit))))
1217 (goto-char cursor-location) ; return to original location
1218 replace)))
1063 1219
1064 1220
1065 (defun ispell-get-word (following &optional extra-otherchars) 1221 (defun ispell-get-word (following &optional extra-otherchars)
1066 "Return the word for spell-checking according to ispell syntax. 1222 "Return the word for spell-checking according to ispell syntax.
1067 If optional argument FOLLOWING is non-nil or if `ispell-following-word' 1223 If optional argument FOLLOWING is non-nil or if `ispell-following-word'
1158 Highlights the word, which is assumed to run from START to END. 1314 Highlights the word, which is assumed to run from START to END.
1159 Global `ispell-pdict-modified-p' becomes a list where the only value 1315 Global `ispell-pdict-modified-p' becomes a list where the only value
1160 indicates whether the dictionary has been modified when option `a' or `i' is 1316 indicates whether the dictionary has been modified when option `a' or `i' is
1161 used. 1317 used.
1162 Global `ispell-quit' set to start location to continue spell session." 1318 Global `ispell-quit' set to start location to continue spell session."
1163 (let ((textbuf (current-buffer)) 1319 (let ((count ?0)
1164 (count ?0) 1320 (line ispell-choices-win-default-height)
1165 (line 2) 1321 (max-lines (- (window-height) 4)) ; ensure 4 context lines.
1166 (max-lines (- (window-height) 4)) ; assure 4 context lines.
1167 (choices miss) 1322 (choices miss)
1168 (window-min-height (min window-min-height 1323 (window-min-height (min window-min-height
1169 ispell-choices-win-default-height)) 1324 ispell-choices-win-default-height))
1170 (command-characters '( ? ?i ?a ?A ?r ?R ?? ?x ?X ?q ?l ?u ?m )) 1325 (command-characters '( ? ?i ?a ?A ?r ?R ?? ?x ?X ?q ?l ?u ?m ))
1171 (dedicated (window-dedicated-p (selected-window))) 1326 (dedicated (window-dedicated-p (selected-window)))
1172 (skipped 0) 1327 (skipped 0)
1173 char num result textwin dedicated-win highlighted) 1328 char num result textwin dedicated-win)
1174 1329
1175 ;; setup the *Choices* buffer with valid data. 1330 ;; setup the *Choices* buffer with valid data.
1176 (save-excursion 1331 (save-excursion
1177 (set-buffer (get-buffer-create ispell-choices-buffer)) 1332 (set-buffer (get-buffer-create ispell-choices-buffer))
1178 (setq mode-line-format (concat "-- %b -- word: " word)) 1333 (setq mode-line-format (concat "-- %b -- word: " word))
1179 (and (fboundp 'set-specifier) ; prevent XEmacs modeline hiding 1334 ;; XEmacs: prevent thick modeline vs increasing height in overlay-window
1180 (set-specifier has-modeline-p (cons (current-buffer) nil))) 1335 ;;(and (fboundp 'set-specifier)
1336 ;; (set-specifier has-modeline-p (cons (current-buffer) nil)))
1181 (erase-buffer) 1337 (erase-buffer)
1182 (if guess 1338 (if guess
1183 (progn 1339 (progn
1184 (insert "Affix rules generate and capitalize " 1340 (insert "Affix rules generate and capitalize "
1185 "this word as shown below:\n\t") 1341 "this word as shown below:\n\t")
1223 (setq dedicated-win (selected-window)) 1379 (setq dedicated-win (selected-window))
1224 (set-window-dedicated-p dedicated-win nil))) 1380 (set-window-dedicated-p dedicated-win nil)))
1225 1381
1226 ;; Display choices for misspelled word. 1382 ;; Display choices for misspelled word.
1227 (ispell-show-choices line end) 1383 (ispell-show-choices line end)
1228
1229 (select-window (setq textwin (next-window))) 1384 (select-window (setq textwin (next-window)))
1230 1385
1231 ;; highlight word, protecting current buffer status 1386 ;; highlight word, protecting current buffer status
1232 (unwind-protect 1387 (unwind-protect
1233 (progn 1388 (progn
1275 ((or (= char ?r) (= char ?R)) ; type in replacement 1430 ((or (= char ?r) (= char ?R)) ; type in replacement
1276 (and (eq 'block ispell-highlight-p) ; refresh tty's 1431 (and (eq 'block ispell-highlight-p) ; refresh tty's
1277 (ispell-highlight-spelling-error start end nil t)) 1432 (ispell-highlight-spelling-error start end nil t))
1278 (let ((result 1433 (let ((result
1279 (if (or (= char ?R) ispell-query-replace-choices) 1434 (if (or (= char ?R) ispell-query-replace-choices)
1280 (list (read-string "Query-replacement for: " 1435 (list (read-string
1281 word) t) 1436 (format "Query-replacement for %s: "word)
1437 word)
1438 t)
1282 (cons (read-string "Replacement for: " word) 1439 (cons (read-string "Replacement for: " word)
1283 nil)))) 1440 nil))))
1284 (and (eq 'block ispell-highlight-p) 1441 (and (eq 'block ispell-highlight-p)
1285 (ispell-highlight-spelling-error start end nil 1442 (ispell-highlight-spelling-error start end nil
1286 'block)) 1443 'block))
1319 ((= char ?l) 1476 ((= char ?l)
1320 (and (eq 'block ispell-highlight-p) ; refresh tty displays 1477 (and (eq 'block ispell-highlight-p) ; refresh tty displays
1321 (ispell-highlight-spelling-error start end nil t)) 1478 (ispell-highlight-spelling-error start end nil t))
1322 (let ((new-word (read-string 1479 (let ((new-word (read-string
1323 "Lookup string (`*' is wildcard): " 1480 "Lookup string (`*' is wildcard): "
1324 word)) 1481 word)))
1325 (new-line 2))
1326 (if new-word 1482 (if new-word
1327 (progn 1483 (progn
1328 (save-excursion 1484 (save-excursion
1329 (set-buffer (get-buffer-create 1485 (set-buffer (get-buffer-create
1330 ispell-choices-buffer)) 1486 ispell-choices-buffer))
1333 skipped 0 1489 skipped 0
1334 mode-line-format (concat 1490 mode-line-format (concat
1335 "-- %b -- word: " 1491 "-- %b -- word: "
1336 new-word) 1492 new-word)
1337 miss (lookup-words new-word) 1493 miss (lookup-words new-word)
1338 choices miss) 1494 choices miss
1495 line ispell-choices-win-default-height)
1339 (while (and choices ; adjust choices window. 1496 (while (and choices ; adjust choices window.
1340 (< (if (> (+ 7 (current-column) 1497 (< (if (> (+ 7 (current-column)
1341 (length (car choices)) 1498 (length (car choices))
1342 (if (> count ?~) 3 0)) 1499 (if (> count ?~) 3 0))
1343 (window-width)) 1500 (window-width))
1344 (progn 1501 (progn
1345 (insert "\n") 1502 (insert "\n")
1346 (setq new-line 1503 (setq line (1+ line)))
1347 (1+ new-line))) 1504 line)
1348 new-line)
1349 max-lines)) 1505 max-lines))
1350 (while (memq count command-characters) 1506 (while (memq count command-characters)
1351 (setq count (ispell-int-char (1+ count)) 1507 (setq count (ispell-int-char (1+ count))
1352 skipped (1+ skipped))) 1508 skipped (1+ skipped)))
1353 (insert "(" count ") " (car choices) " ") 1509 (insert "(" count ") " (car choices) " ")
1354 (setq choices (cdr choices) 1510 (setq choices (cdr choices)
1355 count (ispell-int-char (1+ count)))) 1511 count (ispell-int-char (1+ count))))
1356 (setq count (ispell-int-char 1512 (setq count (ispell-int-char
1357 (- count ?0 skipped)))) 1513 (- count ?0 skipped))))
1358 (select-window (previous-window)) 1514 (ispell-show-choices line end)
1359 (if (and (/= new-line line)
1360 (> (max line new-line)
1361 ispell-choices-win-default-height))
1362 (let* ((minh ispell-choices-win-default-height)
1363 (gr-bl (if (< line minh) ; blanks
1364 (- minh line)
1365 0))
1366 (shr-bl (if (< new-line minh) ; blanks
1367 (- minh new-line)
1368 0)))
1369 (if (> new-line line)
1370 (enlarge-window (- new-line line gr-bl))
1371 (shrink-window (- line new-line shr-bl)))
1372 (setq line new-line)))
1373 (select-window (next-window))))) 1515 (select-window (next-window)))))
1374 (and (eq 'block ispell-highlight-p) 1516 (and (eq 'block ispell-highlight-p)
1375 (ispell-highlight-spelling-error start end nil 1517 (ispell-highlight-spelling-error start end nil
1376 'block)) 1518 'block))
1377 t) ; reselect from new choices 1519 t) ; reselect from new choices
1391 (list (nth num miss) 'query-replace) 1533 (list (nth num miss) 'query-replace)
1392 (nth num miss))) 1534 (nth num miss)))
1393 ((= char ?\C-l) 1535 ((= char ?\C-l)
1394 (redraw-display) t) 1536 (redraw-display) t)
1395 ((= char ?\C-r) 1537 ((= char ?\C-r)
1538 ;; This may have alignment errors if current line is edited
1396 (if (marker-position ispell-recursive-edit-marker) 1539 (if (marker-position ispell-recursive-edit-marker)
1397 (progn 1540 (progn
1398 (message "Only one recursive edit session supported") 1541 (message "Only one recursive edit session supported")
1399 (beep)) 1542 (beep)
1543 (sit-for 2))
1400 (set-marker ispell-recursive-edit-marker start) 1544 (set-marker ispell-recursive-edit-marker start)
1401 ;;(set-marker ispell-region-end reg-end) 1545 ;;(set-marker ispell-region-end reg-end)
1402 (and ispell-highlight-p ; unhighlight 1546 (and ispell-highlight-p ; unhighlight
1403 (ispell-highlight-spelling-error start end)) 1547 (ispell-highlight-spelling-error start end))
1404 (unwind-protect 1548 (unwind-protect
1405 (progn 1549 (progn
1550 (message
1551 "%s"
1552 (substitute-command-keys
1553 (concat "Exit recursive edit with"
1554 " \\[exit-recursive-edit]")))
1406 (save-window-excursion (save-excursion 1555 (save-window-excursion (save-excursion
1407 (recursive-edit)) t) 1556 (recursive-edit))))
1408 (if (not (equal (marker-buffer 1557 ;; protected
1409 ispell-recursive-edit-marker) 1558 (goto-char ispell-recursive-edit-marker)
1410 (current-buffer))) 1559 (if (not (equal (marker-buffer
1411 (error 1560 ispell-recursive-edit-marker)
1412 "Cannot continue ispell from this buffer.")) 1561 (current-buffer)))
1413 (goto-char ispell-recursive-edit-marker)) 1562 (progn
1563 (set-marker ispell-recursive-edit-marker nil)
1564 (error
1565 "Cannot continue ispell from this buffer.")))
1414 (set-marker ispell-recursive-edit-marker nil))) 1566 (set-marker ispell-recursive-edit-marker nil)))
1415 (cons word nil)) ; recheck starting at this word. 1567 (list word nil)) ; recheck starting at this word.
1416 ((= char ?\C-z) 1568 ((= char ?\C-z)
1417 (funcall (key-binding "\C-z")) 1569 (funcall (key-binding "\C-z"))
1418 t) 1570 t)
1419 (t (ding) t)))))) 1571 (t (ding) t))))))
1420 result) 1572 result)
1428 1580
1429 1581
1430 1582
1431 (defun ispell-show-choices (line end) 1583 (defun ispell-show-choices (line end)
1432 "Shows the choices in another buffer or frame." 1584 "Shows the choices in another buffer or frame."
1433 (if ispell-use-framepop-p 1585 (if (and ispell-use-framepop-p (fboundp 'framepop-display-buffer))
1434 (progn 1586 (progn
1435 (framepop-display-buffer (get-buffer ispell-choices-buffer)) 1587 (framepop-display-buffer (get-buffer ispell-choices-buffer))
1436 (get-buffer-window ispell-choices-buffer t) 1588 (get-buffer-window ispell-choices-buffer t)
1437 (select-window (previous-window))) ; *Choices* window 1589 (select-window (previous-window))) ; *Choices* window
1438 ;; standard selection by splitting a small buffer out of this window. 1590 ;; standard selection by splitting a small buffer out of this window.
1527 (help-3 (concat "[u]ncapitalized insert into dict. " 1679 (help-3 (concat "[u]ncapitalized insert into dict. "
1528 "Type 'x C-h d ispell-help' for more help"))) 1680 "Type 'x C-h d ispell-help' for more help")))
1529 (save-window-excursion 1681 (save-window-excursion
1530 (if ispell-help-in-bufferp 1682 (if ispell-help-in-bufferp
1531 (progn 1683 (progn
1532 (ispell-overlay-window 4) 1684 (ispell-overlay-window (if ispell-xemacsp 5 4))
1533 (switch-to-buffer (get-buffer-create "*Ispell Help*")) 1685 (switch-to-buffer (get-buffer-create "*Ispell Help*"))
1534 (insert (concat help-1 "\n" help-2 "\n" help-3)) 1686 (insert (concat help-1 "\n" help-2 "\n" help-3))
1535 (sit-for 5) 1687 (sit-for 5)
1536 (kill-buffer "*Ispell Help*")) 1688 (kill-buffer "*Ispell Help*"))
1537 (select-window (minibuffer-window)) 1689 (select-window (minibuffer-window))
1538 ;;(enlarge-window 2)
1539 (erase-buffer) 1690 (erase-buffer)
1540 (cond ((string-match "Lucid\\|XEmacs" emacs-version) 1691 (if (not ispell-version18p) (message nil))
1541 (message help-3) 1692 ;;(set-minibuffer-window (selected-window))
1542 (enlarge-window 1) 1693 (enlarge-window 2)
1543 (message help-2) 1694 (insert (concat help-1 "\n" help-2 "\n" help-3))
1544 (enlarge-window 1)
1545 (message help-1)
1546 (goto-char (point-min)))
1547 (t
1548 (if (not (string-match "18\\.[0-9]+\\.[0-9]+" emacs-version))
1549 (message nil))
1550 ;;(set-minibuffer-window (selected-window))
1551 (enlarge-window 2)
1552 (insert (concat help-1 "\n" help-2 "\n" help-3))))
1553 (sit-for 5) 1695 (sit-for 5)
1554 (erase-buffer)))))) 1696 (erase-buffer))))))
1555 1697
1556 1698
1557 (defun lookup-words (word &optional lookup-dict) 1699 (defun lookup-words (word &optional lookup-dict)
1712 (delete-overlay ispell-overlay))) 1854 (delete-overlay ispell-overlay)))
1713 1855
1714 1856
1715 (defun ispell-highlight-spelling-error (start end &optional highlight refresh) 1857 (defun ispell-highlight-spelling-error (start end &optional highlight refresh)
1716 (cond 1858 (cond
1717 ((string-match "Lucid\\|XEmacs" emacs-version) 1859 (ispell-xemacsp
1718 (ispell-highlight-spelling-error-xemacs start end highlight)) 1860 (ispell-highlight-spelling-error-xemacs start end highlight))
1719 ((and (not (string-match "18\\.[0-9]+\\.[0-9]+" emacs-version)) 1861 ((and (not ispell-version18p)
1720 (featurep 'faces) window-system) 1862 (featurep 'faces) window-system)
1721 (ispell-highlight-spelling-error-overlay start end highlight)) 1863 (ispell-highlight-spelling-error-overlay start end highlight))
1722 (t (ispell-highlight-spelling-error-generic start end highlight refresh)))) 1864 (t (ispell-highlight-spelling-error-generic start end highlight refresh))))
1723 1865
1724 1866
1731 (top (save-excursion (move-to-window-line height) (point)))) 1873 (top (save-excursion (move-to-window-line height) (point))))
1732 ;; If line above old point (line starting at oldot) would be 1874 ;; If line above old point (line starting at oldot) would be
1733 ;; hidden by new window, scroll it to just below new win 1875 ;; hidden by new window, scroll it to just below new win
1734 ;; otherwise set top line of other win so it doesn't scroll. 1876 ;; otherwise set top line of other win so it doesn't scroll.
1735 (if (< oldot top) (setq top oldot)) 1877 (if (< oldot top) (setq top oldot))
1736 ;; NB: XEmacs 19.9 bug: If a window of size N (N includes the mode
1737 ;; line) is demanded, the last line is not visible.
1738 ;; At least this happens on AIX 3.2, XEmacs w/ Motif, font 9x15.
1739 ;; So we increment the height for this case.
1740 (if (and (string-match "Lucid\\|XEmacs" emacs-version)
1741 (string-match "19\\.9\\.[0-9]+" emacs-version))
1742 (setq height (1+ height)))
1743 ;; if frame is unsplitable, temporarily disable that... 1878 ;; if frame is unsplitable, temporarily disable that...
1744 (if (cdr (assq 'unsplittable (frame-parameters (selected-frame)))) 1879 (if (cdr (assq 'unsplittable (frame-parameters (selected-frame))))
1745 (let ((frame (selected-frame))) 1880 (let ((frame (selected-frame)))
1746 (modify-frame-parameters frame '((unsplittable . nil))) 1881 (modify-frame-parameters frame '((unsplittable . nil)))
1747 (split-window nil height) 1882 (split-window nil height)
1749 (split-window nil height)) 1884 (split-window nil height))
1750 (set-window-start (next-window) top)))) 1885 (set-window-start (next-window) top))))
1751 1886
1752 1887
1753 ;;; Should we add a compound word match return value? 1888 ;;; Should we add a compound word match return value?
1754 (defun ispell-parse-output (output) 1889 (defun ispell-parse-output (output &optional accept-list shift)
1755 "Parse the OUTPUT string from Ispell process and return: 1890 "Parse the OUTPUT string from Ispell process and return:
1756 1: t for an exact match. 1891 1: t for an exact match.
1757 2: A string containing the root word matched via suffix removal. 1892 2: A string containing the root word matched via suffix removal.
1758 3: A list of possible correct spellings of the format: 1893 3: A list of possible correct spellings of the format:
1759 (\"ORIGINAL-WORD\" OFFSET MISS-LIST GUESS-LIST) 1894 (\"ORIGINAL-WORD\" OFFSET MISS-LIST GUESS-LIST)
1760 ORIGINAL-WORD is a string of the possibly misspelled word. 1895 ORIGINAL-WORD is a string of the possibly misspelled word.
1761 OFFSET is an integer giving the line offset of the word. 1896 OFFSET is an integer giving the line offset of the word.
1762 MISS-LIST and GUESS-LIST are possibly null lists of guesses and misses. 1897 MISS-LIST and GUESS-LIST are possibly null lists of guesses and misses.
1763 4: Nil when an error has occurred." 1898 4: Nil when an error has occurred.
1899
1900 Optinal second arg ACCEPT-LIST is list of words already accepted.
1901 Optional third arg SHIFT is an offset to apply based on previous corrections."
1764 (cond 1902 (cond
1765 ((string= output "") t) ; for startup with pipes... 1903 ((string= output "") t) ; for startup with pipes...
1766 ((string= output "*") t) ; exact match 1904 ((string= output "*") t) ; exact match
1767 ((string= output "-") t) ; compound word match 1905 ((string= output "-") t) ; compound word match
1768 ((string= (substring output 0 1) "+") ; found because of root word 1906 ((string= (substring output 0 1) "+") ; found because of root word
1793 (setq guess-list (cons (substring output 0 end) guess-list)) 1931 (setq guess-list (cons (substring output 0 end) guess-list))
1794 (setq miss-list (cons (substring output 0 end) miss-list))) 1932 (setq miss-list (cons (substring output 0 end) miss-list)))
1795 (if (match-end 1) ; True only when at end of line. 1933 (if (match-end 1) ; True only when at end of line.
1796 (setq output nil) ; no more misses or guesses 1934 (setq output nil) ; no more misses or guesses
1797 (setq output (substring output (+ end 2)))))) 1935 (setq output (substring output (+ end 2))))))
1798 (list original-word offset (nreverse miss-list)(nreverse guess-list)))))) 1936 ;; return results. Accept word if it was already accepted.
1799 1937 ;; adjust offset.
1800 1938 (if (member original-word accept-list)
1801 (defun check-ispell-version (&optional interactivep) 1939 t
1802 ;; This is a little wasteful as we actually launch ispell twice: once 1940 (list original-word
1803 ;; to make sure it's the right version, and once for real. But people 1941 (if (numberp shift) (+ shift offset) offset)
1804 ;; get confused by version mismatches *all* the time (and I've got the 1942 (nreverse miss-list) (nreverse guess-list)))))))
1805 ;; email to prove it) so I think this is worthwhile. And the -v[ersion]
1806 ;; option is the only way I can think of to do this that works with
1807 ;; all versions, since versions earlier than 3.0.09 didn't identify
1808 ;; themselves on startup.
1809 (interactive "p")
1810 (let ((result t)
1811 (case-fold-search-val case-fold-search)
1812 ;; avoid bugs when syntax of `.' changes in various default modes
1813 (default-major-mode 'fundamental-mode)
1814 status)
1815 (save-excursion
1816 (set-buffer (get-buffer-create " *ispell-tmp*"))
1817 (erase-buffer)
1818 (setq status (call-process ispell-program-name nil t nil "-v"))
1819 (goto-char (point-min))
1820 (if interactivep
1821 (progn
1822 (end-of-line)
1823 (setq result (concat (buffer-substring-no-properties (point-min)
1824 (point))
1825 ", "
1826 ispell-version))
1827 (message result)
1828 (goto-char (point-min))))
1829 (if (not (memq status '(0 nil)))
1830 (error "%s exited with %s %s" ispell-program-name
1831 (if (stringp status) "signal" "code") status))
1832 (setq case-fold-search t
1833 status (re-search-forward
1834 (concat "\\<\\("
1835 (format "%d" (car ispell-required-version))
1836 "\\)\\.\\([0-9]*\\)\\.\\([0-9]*\\)\\>")
1837 nil t)
1838 case-fold-search case-fold-search-val)
1839 (if (or (not status) ; major version mismatch
1840 (< (car (read-from-string (buffer-substring-no-properties
1841 (match-beginning 2) (match-end 2))))
1842 (car (cdr ispell-required-version)))) ; minor version mismatch
1843 (error "%s version 3 release %d.%d.%d or greater is required"
1844 ispell-program-name (car ispell-required-version)
1845 (car (cdr ispell-required-version))
1846 (car (cdr (cdr ispell-required-version))))
1847 ;; check that it is the correct version.
1848 (if (and (= (car (read-from-string (buffer-substring-no-properties
1849 (match-beginning 2)(match-end 2))))
1850 (car (cdr ispell-required-version)))
1851 (< (car (read-from-string (buffer-substring-no-properties
1852 (match-beginning 3)(match-end 3))))
1853 (car (cdr (cdr ispell-required-version)))))
1854 (setq ispell-offset 0)))
1855 (kill-buffer (current-buffer)))
1856 result))
1857 1943
1858 1944
1859 (defun ispell-init-process () 1945 (defun ispell-init-process ()
1860 "Check status of Ispell process and start if necessary." 1946 "Check status of Ispell process and start if necessary."
1861 (if (and ispell-process 1947 (if (and ispell-process
1894 args))) 1980 args)))
1895 ispell-filter nil 1981 ispell-filter nil
1896 ispell-filter-continue nil 1982 ispell-filter-continue nil
1897 ispell-process-directory default-directory) 1983 ispell-process-directory default-directory)
1898 (set-process-filter ispell-process 'ispell-filter) 1984 (set-process-filter ispell-process 'ispell-filter)
1899 (if (and (boundp 'enable-multibyte-characters) 1985 ;; protect against bogus binding of `enable-multibyte-characters' in XEmacs
1900 (fboundp 'set-process-coding-system) 1986 (if (and (or ispell-xemacsp
1901 enable-multibyte-characters) 1987 (and (boundp 'enable-multibyte-characters)
1988 enable-multibyte-characters))
1989 (fboundp 'set-process-coding-system))
1902 (set-process-coding-system ispell-process (ispell-get-coding-system) 1990 (set-process-coding-system ispell-process (ispell-get-coding-system)
1903 (ispell-get-coding-system))) 1991 (ispell-get-coding-system)))
1904 ;; Get version ID line 1992 ;; Get version ID line
1905 (if (not (string-match "18\\.[0-9]+\\.[0-9]+" emacs-version)) 1993 (if (not ispell-version18p)
1906 (accept-process-output ispell-process 3) 1994 (accept-process-output ispell-process 3)
1907 (accept-process-output ispell-process)) 1995 (accept-process-output ispell-process))
1908 ;; get more output if filter empty? 1996 ;; get more output if filter empty?
1909 (if (null ispell-filter) (accept-process-output ispell-process 3)) 1997 (if (null ispell-filter) (accept-process-output ispell-process 3))
1910 (cond ((null ispell-filter) 1998 (cond ((null ispell-filter)
1911 (error "%s did not output version line" ispell-program-name)) 1999 (error "%s did not output version line" ispell-program-name))
1912 ((and 2000 ((and
1913 (stringp (car ispell-filter)) 2001 (stringp (car ispell-filter))
1914 (if (string-match "warning: " (car ispell-filter)) 2002 (if (string-match "warning: " (car ispell-filter))
1915 (progn 2003 (progn
1916 (if (not (string-match "18\\.[0-9]+\\.[0-9]+" emacs-version)) 2004 (if (not ispell-version18p)
1917 (accept-process-output ispell-process 3) ; was warn msg. 2005 (accept-process-output ispell-process 3) ; was warn msg.
1918 (accept-process-output ispell-process)) 2006 (accept-process-output ispell-process))
1919 (stringp (car ispell-filter))) 2007 (stringp (car ispell-filter)))
1920 (null (cdr ispell-filter))) 2008 (null (cdr ispell-filter)))
1921 (string-match "^@(#) " (car ispell-filter))) 2009 (string-match "^@(#) " (car ispell-filter)))
1950 (accept-process-output ispell-process 1)) 2038 (accept-process-output ispell-process 1))
1951 (if (eq (process-status ispell-process) 'run) 2039 (if (eq (process-status ispell-process) 'run)
1952 (kill-process ispell-process)) 2040 (kill-process ispell-process))
1953 (while (not (or (eq (process-status ispell-process) 'exit) 2041 (while (not (or (eq (process-status ispell-process) 'exit)
1954 (eq (process-status ispell-process) 'signal))) 2042 (eq (process-status ispell-process) 'signal)))
1955 (sleep-for 0 250)) 2043 (if ispell-version20p (sleep-for 0.25)
2044 (sleep-for 0 250)))
1956 (setq ispell-process nil) 2045 (setq ispell-process nil)
1957 (message "Ispell process killed") 2046 (message "Ispell process killed")
1958 nil)) 2047 nil))
1959 2048
1960 2049
2007 2096
2008 2097
2009 ;;; Spelling of comments are checked when ispell-check-comments is non-nil. 2098 ;;; Spelling of comments are checked when ispell-check-comments is non-nil.
2010 2099
2011 ;;;###autoload 2100 ;;;###autoload
2012 (defun ispell-region (reg-start reg-end) 2101 (defun ispell-region (reg-start reg-end &optional recheckp shift)
2013 "Interactively check a region for spelling errors. 2102 "Interactively check a region for spelling errors.
2014 Return non-nil if spell session completed normally." 2103 Return nil if spell session is quit,
2104 otherwise returns shift offset amount for last line processed."
2015 (interactive "r") ; Don't flag errors on read-only bufs. 2105 (interactive "r") ; Don't flag errors on read-only bufs.
2016 (ispell-accept-buffer-local-defs) ; set up dictionary, local words, etc. 2106 (if (not recheckp)
2107 (ispell-accept-buffer-local-defs)) ; set up dictionary, local words, etc.
2017 (unwind-protect 2108 (unwind-protect
2018 (save-excursion 2109 (save-excursion
2019 (message "Spell checking %s using %s dictionary..." 2110 (message "Spell checking %s using %s dictionary..."
2020 (if (and (= reg-start (point-min)) (= reg-end (point-max))) 2111 (if (and (= reg-start (point-min)) (= reg-end (point-max)))
2021 (buffer-name) "region") 2112 (buffer-name) "region")
2022 (or ispell-dictionary "default")) 2113 (or ispell-dictionary "default"))
2023 ;; Returns cursor to original location. 2114 ;; Returns cursor to original location.
2024 (save-window-excursion 2115 (save-window-excursion
2025 (goto-char reg-start) 2116 (goto-char reg-start)
2026 (let ((transient-mark-mode nil) 2117 (let ((transient-mark-mode)
2027 (case-fold-search case-fold-search) 2118 (case-fold-search case-fold-search)
2028 (skip-region-start (make-marker)) 2119 (skip-region-start (make-marker))
2029 (skip-regexp (ispell-begin-skip-region-regexp)) 2120 (skip-regexp (ispell-begin-skip-region-regexp))
2030 (skip-alist ispell-skip-region-alist) 2121 (skip-alist ispell-skip-region-alist)
2031 key) 2122 key)
2072 (let* ((start (point)) 2163 (let* ((start (point))
2073 (end (save-excursion (end-of-line) (min (point) reg-end))) 2164 (end (save-excursion (end-of-line) (min (point) reg-end)))
2074 (string (ispell-get-line start end reg-end))) 2165 (string (ispell-get-line start end reg-end)))
2075 (setq end (point)) ; "end" tracks region retrieved. 2166 (setq end (point)) ; "end" tracks region retrieved.
2076 (if string ; there is something to spell check! 2167 (if string ; there is something to spell check!
2077 (ispell-process-line string)) ; (special start end) 2168 ;; (special start end)
2169 (setq shift (ispell-process-line string
2170 (and recheckp shift))))
2078 (goto-char end))))) 2171 (goto-char end)))))
2079 (not ispell-quit)) 2172 (if ispell-quit
2173 nil
2174 (or shift 0)))
2080 ;; protected 2175 ;; protected
2081 (if (get-buffer ispell-choices-buffer) 2176 (if (and (not (and recheckp ispell-keep-choices-win))
2177 (get-buffer ispell-choices-buffer))
2082 (kill-buffer ispell-choices-buffer)) 2178 (kill-buffer ispell-choices-buffer))
2083 (if ispell-quit 2179 (if ispell-quit
2084 (progn 2180 (progn
2085 ;; preserve or clear the region for ispell-continue. 2181 ;; preserve or clear the region for ispell-continue.
2086 (if (not (numberp ispell-quit)) 2182 (if (not (numberp ispell-quit))
2090 ;; Check for aborting 2186 ;; Check for aborting
2091 (if (and ispell-checking-message (numberp ispell-quit)) 2187 (if (and ispell-checking-message (numberp ispell-quit))
2092 (progn 2188 (progn
2093 (setq ispell-quit nil) 2189 (setq ispell-quit nil)
2094 (error "Message send aborted"))) 2190 (error "Message send aborted")))
2095 (setq ispell-quit nil)) 2191 (if (not recheckp) (setq ispell-quit nil)))
2096 (set-marker ispell-region-end nil) 2192 (if (not recheckp) (set-marker ispell-region-end nil))
2097 ;; Only save if successful exit. 2193 ;; Only save if successful exit.
2098 (ispell-pdict-save ispell-silently-savep) 2194 (ispell-pdict-save ispell-silently-savep)
2099 (message "Spell-checking done")))) 2195 (message "Spell-checking done"))))
2100 2196
2101 2197
2116 (setq skip-regexp (concat ispell-tib-ref-beginning "\\|" skip-regexp))) 2212 (setq skip-regexp (concat ispell-tib-ref-beginning "\\|" skip-regexp)))
2117 (if ispell-skip-sgml 2213 (if ispell-skip-sgml
2118 (setq skip-regexp (concat "<author>" "\\|" 2214 (setq skip-regexp (concat "<author>" "\\|"
2119 "<[cC][oO][dD][eE]>" "\\|" 2215 "<[cC][oO][dD][eE]>" "\\|"
2120 "<[vV][eE][rR][bB]>" "\\|" 2216 "<[vV][eE][rR][bB]>" "\\|"
2121 "<[tT][tT]>" "\\|" 2217 ;; "<[tT][tT]>" "\\|"
2122 "<[tT][tT]/" "\\|" 2218 "<[tT][tT]/" "\\|"
2123 "</" "\\|" 2219 "</" "\\|"
2124 "<" "\\|" 2220 "<" "\\|"
2125 "&" "\\|" 2221 "&" "\\|"
2126 skip-regexp))) 2222 skip-regexp)))
2192 (search-forward ">" ispell-region-end t)) 2288 (search-forward ">" ispell-region-end t))
2193 ((and ispell-skip-sgml (string-match "<[cC][oO][dD][eE]>" key)) 2289 ((and ispell-skip-sgml (string-match "<[cC][oO][dD][eE]>" key))
2194 (search-forward-regexp "</[cC][oO][dD][eE]>" ispell-region-end t)) 2290 (search-forward-regexp "</[cC][oO][dD][eE]>" ispell-region-end t))
2195 ((and ispell-skip-sgml (string-match "<[vV][eE][rR][bB]>" key)) 2291 ((and ispell-skip-sgml (string-match "<[vV][eE][rR][bB]>" key))
2196 (search-forward-regexp "</[vV][eE][rR][bB]>" ispell-region-end t)) 2292 (search-forward-regexp "</[vV][eE][rR][bB]>" ispell-region-end t))
2197 ((and ispell-skip-sgml (string-match "<[tT][tT]>" key)) 2293 ;;((and ispell-skip-sgml (string-match "<[tT][tT]>" key))
2198 (search-forward-regexp "</[tT][tT]>" ispell-region-end t)) 2294 ;; (search-forward-regexp "</[tT][tT]>" ispell-region-end t))
2199 ((and ispell-skip-sgml (string-match "<[tT][tT]/" key)) 2295 ((and ispell-skip-sgml (string-match "<[tT][tT]/" key))
2200 (search-forward "/" ispell-region-end t)) 2296 (search-forward "/" ispell-region-end t))
2201 ((and ispell-skip-sgml (string-match "<" key)) 2297 ((and ispell-skip-sgml (string-match "<" key))
2202 (search-forward-regexp "[/>]" ispell-region-end t)) 2298 (search-forward-regexp "[/>]" ispell-region-end t))
2203 ((and ispell-skip-sgml (string-match "&" key)) 2299 ((and ispell-skip-sgml (string-match "&" key))
2248 (goto-char end)) 2344 (goto-char end))
2249 (t (goto-char end))) ; EMPTY LINE, skip it. 2345 (t (goto-char end))) ; EMPTY LINE, skip it.
2250 string)) 2346 string))
2251 2347
2252 2348
2253 (defun ispell-process-line (string) 2349 (defun ispell-process-line (string shift)
2350 "Sends a LINE of text to ispell and processes the result.
2351 This will modify the buffer for spelling errors.
2352 Requires variables START and END to be defined in its lexical scope.
2353 Returns the sum shift due to changes in word replacements."
2254 ;;(declare special start end) 2354 ;;(declare special start end)
2255 (let (poss 2355 (let (poss accept-list)
2256 ;; line-offset is the change so far in the size of the line. 2356 (if (not (numberp shift))
2257 ;; The position values we get from ispell reflect the original 2357 (setq shift 0))
2258 ;; text, and correction of previous words may have shifted the
2259 ;; current word within the line.
2260 (line-offset 0))
2261 ;; send string to spell process and get input. 2358 ;; send string to spell process and get input.
2262 (process-send-string ispell-process string) 2359 (process-send-string ispell-process string)
2263 (while (progn 2360 (while (progn
2264 (accept-process-output ispell-process) 2361 (accept-process-output ispell-process)
2265 ;; Last item of output contains a blank line. 2362 ;; Last item of output contains a blank line.
2266 (not (string= "" (car ispell-filter))))) 2363 (not (string= "" (car ispell-filter)))))
2267 ;; parse all inputs from the stream one word at a time. 2364 ;; parse all inputs from the stream one word at a time.
2268 ;; Place in FIFO order and remove the blank item. 2365 ;; Place in FIFO order and remove the blank item.
2269 (setq ispell-filter (nreverse (cdr ispell-filter))) 2366 (setq ispell-filter (nreverse (cdr ispell-filter)))
2270 (while (and (not ispell-quit) ispell-filter) 2367 (while (and (not ispell-quit) ispell-filter)
2271 (setq poss (ispell-parse-output (car ispell-filter))) 2368 ;; get next word, accounting for accepted words and start shifts
2369 (setq poss (ispell-parse-output (car ispell-filter)
2370 accept-list shift))
2272 (if (and poss (listp poss)) ; spelling error occurred. 2371 (if (and poss (listp poss)) ; spelling error occurred.
2273 ;; Whenever we have misspellings, we can change 2372 ;; Whenever we have misspellings, we can change
2274 ;; the buffer. Keep boundaries as markers. 2373 ;; the buffer. Keep boundaries as markers.
2275 ;; Markers can move with highlighting! This destroys 2374 ;; Markers can move with highlighting! This destroys
2276 ;; end of region markers line-end and ispell-region-end 2375 ;; end of region markers line-end and ispell-region-end
2277 (let ((word-start 2376 (let ((word-start
2278 (copy-marker (+ start ispell-offset line-offset 2377 (copy-marker (+ start ispell-offset (car (cdr poss)))))
2279 (car (cdr poss)))))
2280 (word-len (length (car poss))) 2378 (word-len (length (car poss)))
2281 (line-end (copy-marker end)) 2379 (line-end (copy-marker end))
2282 (line-start (copy-marker start)) 2380 (line-start (copy-marker start))
2283 recheck-region replace) 2381 recheck-region replace)
2284 (goto-char word-start) 2382 (goto-char word-start)
2286 (ispell-horiz-scroll) 2384 (ispell-horiz-scroll)
2287 (goto-char (+ word-len word-start)) 2385 (goto-char (+ word-len word-start))
2288 (ispell-horiz-scroll) 2386 (ispell-horiz-scroll)
2289 (goto-char word-start) 2387 (goto-char word-start)
2290 (ispell-horiz-scroll) 2388 (ispell-horiz-scroll)
2389
2390 ;; Alignment cannot be tracked and this error will occur when
2391 ;; `query-replace' makes multiple corrections on the starting line.
2291 (if (/= (+ word-len (point)) 2392 (if (/= (+ word-len (point))
2292 (progn 2393 (progn
2394 ;; NB: Search can fail with Mule character sets that don't
2395 ;; display properly. Ignore the error in this case?
2293 (search-forward (car poss) (+ word-len (point)) t) 2396 (search-forward (car poss) (+ word-len (point)) t)
2294 (point))) 2397 (point)))
2295 ;; This occurs due to filter pipe problems 2398 ;; This occurs due to filter pipe problems
2296 (error (concat "Ispell misalignment: word " 2399 (error (concat "Ispell misalignment: word "
2297 "`%s' point %d; probably incompatible versions") 2400 "`%s' point %d; probably incompatible versions")
2298 (car poss) (marker-position word-start))) 2401 (car poss) (marker-position word-start)))
2299
2300 ;; ispell-cmd-loop can go recursive & change buffer 2402 ;; ispell-cmd-loop can go recursive & change buffer
2301 (if ispell-keep-choices-win 2403 (if ispell-keep-choices-win
2302 (setq replace (ispell-command-loop 2404 (setq replace (ispell-command-loop
2303 (car (cdr (cdr poss))) 2405 (car (cdr (cdr poss)))
2304 (car (cdr (cdr (cdr poss)))) 2406 (car (cdr (cdr (cdr poss))))
2309 (car (cdr (cdr poss))) 2411 (car (cdr (cdr poss)))
2310 (car (cdr (cdr (cdr poss)))) 2412 (car (cdr (cdr (cdr poss))))
2311 (car poss) (marker-position word-start) 2413 (car poss) (marker-position word-start)
2312 (+ word-len (marker-position word-start)))))) 2414 (+ word-len (marker-position word-start))))))
2313 2415
2314 ;; Recheck when recursive edit changes misspelled word
2315 (goto-char word-start) 2416 (goto-char word-start)
2316 (if (not (string-equal (buffer-substring-no-properties 2417 ;; Recheck when query replace edit changes misspelled word.
2317 (point) (+ word-len (point))) 2418 ;; Error in tex mode when a potential math mode change exists.
2318 (car poss))) 2419 (if (and replace (listp replace) (= 2 (length replace)))
2319 (progn 2420 (if (and (eq ispell-parser 'tex)
2421 (string-match "[\\\\][]()[]\\|\\\\begin\\|\\$"
2422 (regexp-quote string)))
2423 (error
2424 "Don't start query replace on a line with math characters"
2425 )
2320 (set-marker line-end (point)) 2426 (set-marker line-end (point))
2321 (setq ispell-filter nil 2427 (setq ispell-filter nil
2322 recheck-region t))) 2428 recheck-region t)))
2323 2429
2430 ;; insert correction if needed
2324 (cond 2431 (cond
2325 ((and replace (listp replace)) 2432 ((or (null replace)
2326 ;; REPLACEMENT WORD 2433 (equal 0 replace)) ; ACCEPT/INSERT
2327 ;; Recheck line starting with the replacement word. 2434 (if (equal 0 replace) ; BUFFER-LOCAL DICT ADD
2328 (setq ispell-filter nil 2435 (ispell-add-per-file-word-list (car poss)))
2329 recheck-region t) 2436 ;; do not recheck accepted word on this line
2437 (setq accept-list (cons (car poss) accept-list)))
2438 (t ; replacement word selected or entered
2330 (delete-region (point) (+ word-len (point))) 2439 (delete-region (point) (+ word-len (point)))
2331 (insert (car replace)) 2440 (if (not (listp replace))
2332 (setq line-offset (+ line-offset (- line-end end))) 2441 (progn
2333 ;; Only typed-in replacements need to be re-checked. 2442 (insert replace) ; insert dictionary word
2334 (if (not (eq 'query-replace (car (cdr replace)))) 2443 (setq accept-list (cons replace accept-list)))
2335 (backward-char (length (car replace)))) 2444 (let ((replace-word (car replace)))
2336 (set-marker line-end (point)) ; continue checking from here. 2445 ;; Recheck hand entered replacement word
2337 (if (car (cdr replace)) 2446 (insert replace-word)
2338 (unwind-protect 2447 (if (car (cdr replace))
2339 (save-window-excursion 2448 (save-window-excursion
2340 (delete-other-windows) ; to correctly show help. 2449 (delete-other-windows) ; to correctly show help.
2341 ;; Assume case-replace & 2450 ;; Assume case-replace &
2342 ;; case-fold-search correct? 2451 ;; case-fold-search correct?
2343 (query-replace (car poss) (car replace) t)) 2452 (query-replace (car poss) (car replace) t)))
2344 (goto-char word-start)))) 2453 (goto-char word-start)
2345 ((or (null replace) 2454 ;; do not recheck if already accepted
2346 (equal 0 replace)) ; ACCEPT/INSERT 2455 (if (member replace-word accept-list)
2347 (if (equal 0 replace) ; BUFFER-LOCAL DICT ADD 2456 (setq accept-list (cons replace-word accept-list)
2348 (ispell-add-per-file-word-list (car poss))) 2457 replace replace-word)
2349 ;; This avoids pointing out the word that was 2458 (let ((region-end (copy-marker ispell-region-end)))
2350 ;; just accepted (via 'i' or 'a') if it follows 2459 (setq recheck-region ispell-filter
2351 ;; on the same line. 2460 ispell-filter nil ; save filter
2352 ;; Redo check following the accepted word. 2461 shift (ispell-region
2353 (if (and ispell-pdict-modified-p 2462 word-start
2354 (listp ispell-pdict-modified-p)) 2463 (+ word-start (length replace-word))
2355 ;; Word accepted. Recheck line. 2464 t shift))
2356 (progn 2465 (if (null shift) ; quitting check.
2357 (setq ispell-pdict-modified-p ;update flag 2466 (setq shift 0))
2358 (car ispell-pdict-modified-p) 2467 (set-marker ispell-region-end region-end)
2359 ispell-filter nil 2468 (set-marker region-end nil)
2360 recheck-region t) 2469 (setq ispell-filter recheck-region
2361 (set-marker line-end (marker-position word-start))))) 2470 recheck-region nil
2362 (replace ; STRING REPLACEMENT for this word. 2471 replace replace-word)))))
2363 (delete-region (point) (+ word-len (point))) 2472
2364 (insert replace) 2473 (setq shift (+ shift (- (length replace) word-len)))
2365 (setq line-offset (+ line-offset (- line-end end))) 2474
2366 2475 ;; Move line-start across word...
2367 (set-marker line-start (+ line-start 2476 ;; new shift function does this now...
2368 (- (length replace) 2477 ;;(set-marker line-start (+ line-start
2369 (length (car poss))))))) 2478 ;; (- (length replace)
2479 ;; (length (car poss)))))
2480 ))
2370 (if (not ispell-quit) 2481 (if (not ispell-quit)
2371 (let (message-log-max) 2482 (let (message-log-max)
2372 (message "Continuing spelling check using %s dictionary..." 2483 (message "Continuing spelling check using %s dictionary..."
2373 (or ispell-dictionary "default")))) 2484 (or ispell-dictionary "default"))))
2374 (sit-for 0) 2485 (sit-for 0)
2382 ;; going out of scope - unneeded 2493 ;; going out of scope - unneeded
2383 (set-marker line-start nil) 2494 (set-marker line-start nil)
2384 (set-marker word-start nil) 2495 (set-marker word-start nil)
2385 (set-marker line-end nil))) 2496 (set-marker line-end nil)))
2386 ;; finished with misspelling! 2497 ;; finished with misspelling!
2387 (setq ispell-filter (cdr ispell-filter))))) 2498 (setq ispell-filter (cdr ispell-filter)))
2499 shift))
2388 2500
2389 2501
2390 ;;;###autoload 2502 ;;;###autoload
2391 (defun ispell-comments-and-strings () 2503 (defun ispell-comments-and-strings ()
2392 "Check comments and strings in the current buffer for spelling errors." 2504 "Check comments and strings in the current buffer for spelling errors."
2890 (forward-line 1) 3002 (forward-line 1)
2891 (insert comment-end))))) 3003 (insert comment-end)))))
2892 (insert (concat " " word)))))))) 3004 (insert (concat " " word))))))))
2893 3005
2894 3006
2895 (defconst ispell-version "ispell.el 3.2 -- Fri May 7 14:25:14 PDT 1999")
2896
2897 (provide 'ispell) 3007 (provide 'ispell)
2898 3008
2899 3009
2900 ;;; LOCAL VARIABLES AND BUFFER-LOCAL VALUE EXAMPLES. 3010 ;;; LOCAL VARIABLES AND BUFFER-LOCAL VALUE EXAMPLES.
2901 3011
2909 3019
2910 ;;; Local Variables: 3020 ;;; Local Variables:
2911 ;;; mode: emacs-lisp 3021 ;;; mode: emacs-lisp
2912 ;;; comment-column: 40 3022 ;;; comment-column: 40
2913 ;;; ispell-check-comments: exclusive 3023 ;;; ispell-check-comments: exclusive
2914 ;;; Local IspellDict: "american" 3024 ;;; ispell-local-dictionary: "american"
2915 ;;; End: 3025 ;;; End:
2916 3026
2917 3027
2918 ;;; MORE EXAMPLES OF ISPELL BUFFER-LOCAL VALUES 3028 ;;; MORE EXAMPLES OF ISPELL BUFFER-LOCAL VALUES
2919 3029
2927 ; LocalWords: Francais Nederlands charset autoloaded popup nonmenu regexp num 3037 ; LocalWords: Francais Nederlands charset autoloaded popup nonmenu regexp num
2928 ; LocalWords: AMStex hspace includeonly nocite epsfig displaymath eqnarray reg 3038 ; LocalWords: AMStex hspace includeonly nocite epsfig displaymath eqnarray reg
2929 ; LocalWords: minipage modeline pers dict unhighlight buf grep sync prev inc 3039 ; LocalWords: minipage modeline pers dict unhighlight buf grep sync prev inc
2930 ; LocalWords: fn hilight oldot NB AIX msg init read's bufs pt cmd Quinlan eg 3040 ; LocalWords: fn hilight oldot NB AIX msg init read's bufs pt cmd Quinlan eg
2931 ; LocalWords: uuencoded unidiff sc nn VM SGML eval IspellPersDict unsplitable 3041 ; LocalWords: uuencoded unidiff sc nn VM SGML eval IspellPersDict unsplitable
2932 ; LocalWords: lns 3042 ; LocalWords: lns XEmacs HTML casechars Multibyte
2933 3043
2934 ;;; ispell.el ends here 3044 ;;; ispell.el ends here