comparison lisp/textmodes/ispell.el @ 28563:7d8ea470609b

(ispell-menu-map): Menu items rearranged and converted to the new menu-item format, names silightly changed, help strings added. Support for spelling without async subprocesses: (ispell-cmd-args, ispell-output-buffer) (ispell-session-buffer): New variables. (ispell-start-process, ispell-process-status, ispell-accept-output, ispell-send-string): New functions, for Ispell invocation when async subprocesses aren't supported. (ispell-word, ispell-pdict-save, ispell-command-loop, ispell-process-line, ispell-buffer-local-parsing): Replace calls to process-send-string with calls to ispell-send-string, and accept-process-output with ispell-accept-output. (ispell-init-process): Call ispell-process-status instead of process-status with. (ispell-init-process): Call ispell-start-process. Call ispell-accept-output and ispell-send-string. Don't call process-kill-without-query and kill-process if they are unbound. (ispell-async-processp): New function.
author Eli Zaretskii <eliz@gnu.org>
date Thu, 13 Apr 2000 14:01:10 +0000
parents ec1a21729421
children 313ef0d76864
comparison
equal deleted inserted replaced
28562:374cbdbde9bd 28563:7d8ea470609b
1 ;;; ispell.el --- Interface to International Ispell Versions 3.1 and 3.2 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, 2000 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: Mon 29 Nov 11:38:34 PST 1999 6 ;; Stevens Mod Date: Fri Jan 28 17:16:58 PST 2000
7 ;; Stevens Revision: 3.3 7 ;; Stevens Revision: 3.4 beta
8 ;; Status : Release with 3.1.12+ and 3.2.0+ 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.
124 ;; can cause misalignment errors. 124 ;; can cause misalignment errors.
125 125
126 ;; HISTORY 126 ;; HISTORY
127 127
128 ;; Modifications made in latest versions: 128 ;; Modifications made in latest versions:
129
130 ;; Revision 3.4 beta 2000/1/28 17:16:58 kss
131 ;; one arg always for xemacs sleep-for (gunnar Evermann)
132 ;; support for synchronous processes (Eli Zaretskii)
129 133
130 ;; Revision 3.3 1999/11/29 11:38:34 kss 134 ;; Revision 3.3 1999/11/29 11:38:34 kss
131 ;; Only word replacements entered in from the keyboard are rechecked. 135 ;; Only word replacements entered in from the keyboard are rechecked.
132 ;; This fixes a bug in tex parsing and misalignment. 136 ;; This fixes a bug in tex parsing and misalignment.
133 ;; Exceptions exist for recursive edit and query-replace, with tex error 137 ;; Exceptions exist for recursive edit and query-replace, with tex error
181 (if (fboundp 'defgroup) 185 (if (fboundp 'defgroup)
182 (defgroup ispell nil 186 (defgroup ispell nil
183 "User variables for emacs ispell interface." 187 "User variables for emacs ispell interface."
184 :group 'applications))) 188 :group 'applications)))
185 189
186 190 (if (not (fboundp 'buffer-substring-no-properties))
187 ;;;###autoload 191 (defun buffer-substring-no-properties (start end)
188 (defconst ispell-xemacsp (string-match "Lucid\\|XEmacs" emacs-version) 192 (buffer-substring start end)))
193
194 ;;;###autoload
195 (defconst xemacsp (string-match "Lucid\\|XEmacs" emacs-version)
189 "Non nil if using XEmacs.") 196 "Non nil if using XEmacs.")
190 197
191 ;;;###autoload 198 ;;;###autoload
192 (defconst ispell-version18p (string-match "18\\.[0-9]+\\.[0-9]+" emacs-version) 199 (defconst version18p (string-match "18\\.[0-9]+\\.[0-9]+" emacs-version)
193 "Non nil if using emacs version 18.") 200 "Non nil if using emacs version 18.")
194 201
195 ;;;###autoload 202 ;;;###autoload
196 (defconst ispell-version20p (string-match "20\\.[0-9]+\\.[0-9]+" emacs-version) 203 (defconst version20p (string-match "20\\.[0-9]+\\.[0-9]+" emacs-version)
197 "Non nil if using emacs version 20.") 204 "Non nil if using emacs version 20.")
205
206 (and (not version18p)
207 (not (boundp 'epoch::version))
208 (defalias 'ispell 'ispell-buffer)
209 (defalias 'ispell-check-version 'check-ispell-version))
198 210
199 211
200 ;;; ********************************************************************** 212 ;;; **********************************************************************
201 ;;; The following variables should be set according to personal preference 213 ;;; The following variables should be set according to personal preference
202 ;;; and location of binaries: 214 ;;; and location of binaries:
256 "*When not nil, the `*Choices*' window remains for spelling session. 268 "*When not nil, the `*Choices*' window remains for spelling session.
257 This minimizes redisplay thrashing." 269 This minimizes redisplay thrashing."
258 :type 'boolean 270 :type 'boolean
259 :group 'ispell) 271 :group 'ispell)
260 272
261 (defcustom ispell-choices-win-default-height (if ispell-xemacsp 3 2) 273 (defcustom ispell-choices-win-default-height (if xemacsp 3 2)
262 "*The default size of the `*Choices*' window, including mode line. 274 "*The default size of the `*Choices*' window, including mode line.
263 Must be greater than 1. 275 Must be greater than 1.
264 XEmacs modeline is thicker than a line of text, so it partially covers the 276 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 277 last line of text in the buffer. Include an extra line in XEmacs to see
266 all of the choices clearly." 278 all of the choices clearly."
424 "*If non-nil, a list of extra switches to pass to the Ispell program. 436 "*If non-nil, a list of extra switches to pass to the Ispell program.
425 For example, (\"-W\" \"3\") to cause it to accept all 1-3 character 437 For example, (\"-W\" \"3\") to cause it to accept all 1-3 character
426 words as correct. See also `ispell-dictionary-alist', which may be used 438 words as correct. See also `ispell-dictionary-alist', which may be used
427 for language-specific arguments." 439 for language-specific arguments."
428 :type '(repeat string) 440 :type '(repeat string)
441 :group 'ispell)
442
443
444
445 (defcustom ispell-skip-sgml 'use-mode-name
446 "*Indicates whether ispell should skip spell checking of SGML markup.
447 If t, always skip SGML markup; if nil, never skip; if non-t and non-nil,
448 guess whether SGML markup should be skipped according to the name of the
449 buffer's major mode."
450 :type '(choice (const :tag "always" t) (const :tag "never" nil)
451 (const :tag "use-mode-name" use-mode-name))
429 :group 'ispell) 452 :group 'ispell)
430 453
431 454
432 ;;; Define definitions here only for personal dictionaries. 455 ;;; Define definitions here only for personal dictionaries.
433 ;;;###autoload 456 ;;;###autoload
463 ispell-dictionary-alist-1 486 ispell-dictionary-alist-1
464 '((nil ; default (English.aff) 487 '((nil ; default (English.aff)
465 "[A-Za-z]" "[^A-Za-z]" "[']" nil ("-B") nil iso-8859-1) 488 "[A-Za-z]" "[^A-Za-z]" "[']" nil ("-B") nil iso-8859-1)
466 ("american" ; Yankee English 489 ("american" ; Yankee English
467 "[A-Za-z]" "[^A-Za-z]" "[']" nil ("-B") nil iso-8859-1) 490 "[A-Za-z]" "[^A-Za-z]" "[']" nil ("-B") nil iso-8859-1)
468 ("brasiliano" ; Brazilian mode 491 ("brasileiro" ; 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]" 492 "[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]" 493 "[^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) 494 "[']" nil ("-d" "brasileiro") nil iso-8859-1)
472 ("british" ; British version 495 ("british" ; British version
473 "[A-Za-z]" "[^A-Za-z]" "[']" nil ("-B" "-d" "british") nil iso-8859-1) 496 "[A-Za-z]" "[^A-Za-z]" "[']" nil ("-B" "-d" "british") nil iso-8859-1)
650 (append ispell-local-dictionary-alist ; dictionary customizations 673 (append ispell-local-dictionary-alist ; dictionary customizations
651 ispell-dictionary-alist-1 ispell-dictionary-alist-2 674 ispell-dictionary-alist-1 ispell-dictionary-alist-2
652 ispell-dictionary-alist-3 ispell-dictionary-alist-4 675 ispell-dictionary-alist-3 ispell-dictionary-alist-4
653 ispell-dictionary-alist-5 ispell-dictionary-alist-6)) 676 ispell-dictionary-alist-5 ispell-dictionary-alist-6))
654 677
655 ;;; The preparation of the menu bar menu must be autoloaded 678
656 ;;; because otherwise this file gets autoloaded every time Emacs starts 679
657 ;;; so that it can set up the menus and determine keyboard equivalents. 680
681 ;;; **********************************************************************
682 ;;; The following are used by ispell, and should not be changed.
683 ;;; **********************************************************************
684
658 685
659 686
660 ;;; The version must be 3.1 or greater for this version of ispell.el 687 ;;; 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. 688 ;;; There is an incompatibility between version 3.1.12 and lower versions.
662 (defconst ispell-required-version '(3 1 12) 689 (defconst ispell-required-version '(3 1 12)
663 "Ispell versions with which this version of ispell.el is known to work.") 690 "Ispell versions with which this version of ispell.el is known to work.")
664 (defvar ispell-offset -1 691 (defvar ispell-offset -1
665 "Offset that maps protocol differences between ispell 3.1 versions.") 692 "Offset that maps protocol differences between ispell 3.1 versions.")
666 693
667 (defconst ispell-version "ispell.el 3.3 -- Mon 29 Nov 11:38:34 PST 1999") 694 (defconst ispell-version "ispell.el 3.4 beta -- Fri Jan 28 17:16:58 PST 2000")
668 695
669 696
670 (defun check-ispell-version (&optional interactivep) 697 (defun check-ispell-version (&optional interactivep)
671 "Ensure that `ispell-program-name' is valid and the correct version. 698 "Ensure that `ispell-program-name' is valid and the correct version.
672 Returns version number if called interactively. 699 Returns version number if called interactively.
729 (setq ispell-offset 0))) 756 (setq ispell-offset 0)))
730 (kill-buffer (current-buffer))) 757 (kill-buffer (current-buffer)))
731 result)) 758 result))
732 759
733 760
761
762 ;;; The preparation of the menu bar menu must be autoloaded
763 ;;; because otherwise this file gets autoloaded every time Emacs starts
764 ;;; so that it can set up the menus and determine keyboard equivalents.
765
766
734 ;;;###autoload 767 ;;;###autoload
735 (defvar ispell-menu-map nil "Key map for ispell menu.") 768 (defvar ispell-menu-map nil "Key map for ispell menu.")
736 ;;; redo menu when loading ispell to get dictionary modifications 769 ;;; redo menu when loading ispell to get dictionary modifications
737 (setq ispell-menu-map nil) 770 (setq ispell-menu-map nil)
738 771
748 ;;; Set up dictionary 781 ;;; Set up dictionary
749 ;;;###autoload 782 ;;;###autoload
750 (defvar ispell-menu-map-needed 783 (defvar ispell-menu-map-needed
751 ;; only needed when not version 18 and not XEmacs. 784 ;; only needed when not version 18 and not XEmacs.
752 (and (not ispell-menu-map) 785 (and (not ispell-menu-map)
753 (not ispell-version18p) 786 (not version18p)
754 (not ispell-xemacsp) 787 (not xemacsp)
755 'reload)) 788 'reload))
756 789
757 (defvar ispell-library-path (check-ispell-version) 790 (defvar ispell-library-path (check-ispell-version)
758 "The directory where ispell dictionaries reside.") 791 "The directory where ispell dictionaries reside.")
759 792
771 load-dict (car (cdr (member "-d" (nth 5 (car dicts))))) 804 load-dict (car (cdr (member "-d" (nth 5 (car dicts)))))
772 dicts (cdr dicts)) 805 dicts (cdr dicts))
773 (cond ((not (stringp name)) 806 (cond ((not (stringp name))
774 (define-key ispell-menu-map (vector 'default) 807 (define-key ispell-menu-map (vector 'default)
775 (cons "Select Default Dict" 808 (cons "Select Default Dict"
776 (list 'lambda () '(interactive) 809 (cons "Dictionary for which Ispell was configured"
777 (list 'ispell-change-dictionary "default"))))) 810 (list 'lambda () '(interactive)
811 (list
812 'ispell-change-dictionary "default"))))))
778 ((or (not path) ; load all if library dir not defined 813 ((or (not path) ; load all if library dir not defined
779 (file-exists-p (concat path "/" name ".hash")) 814 (file-exists-p (concat path "/" name ".hash"))
780 (file-exists-p (concat path "/" name ".has")) 815 (file-exists-p (concat path "/" name ".has"))
781 (and load-dict 816 (and load-dict
782 (or (file-exists-p(concat path "/" load-dict ".hash")) 817 (or (file-exists-p(concat path "/" load-dict ".hash"))
783 (file-exists-p(concat path "/" load-dict ".has"))))) 818 (file-exists-p(concat path "/" load-dict ".has")))))
784 (define-key ispell-menu-map (vector (intern name)) 819 (define-key ispell-menu-map (vector (intern name))
785 (cons (concat "Select " (capitalize name)) 820 (cons (concat "Select " (capitalize name) " Dict")
786 (list 'lambda () '(interactive) 821 (list 'lambda () '(interactive)
787 (list 'ispell-change-dictionary name))))))))) 822 (list 'ispell-change-dictionary name)))))))))
788 823
789 824
790 ;;; define commands in menu in opposite order you want them to appear. 825 ;;; define commands in menu in opposite order you want them to appear.
791 ;;;###autoload 826 ;;;###autoload
792 (if ispell-menu-map-needed 827 (if ispell-menu-map-needed
793 (progn 828 (progn
794 (define-key ispell-menu-map [ispell-change-dictionary] 829 (define-key ispell-menu-map [ispell-change-dictionary]
795 '("Change Dictionary" . ispell-change-dictionary)) 830 '(menu-item "Change Dictionary..." ispell-change-dictionary
831 :help "Supply explicit path to dictionary"))
796 (define-key ispell-menu-map [ispell-kill-ispell] 832 (define-key ispell-menu-map [ispell-kill-ispell]
797 '("Kill Process" . ispell-kill-ispell)) 833 '(menu-item "Kill Process" ispell-kill-ispell
834 :enable (and ispell-process
835 (eq (ispell-process-status) 'run))
836 :help "Terminate Ispell subprocess"))
798 (define-key ispell-menu-map [ispell-pdict-save] 837 (define-key ispell-menu-map [ispell-pdict-save]
799 '("Save Dictionary" . (lambda () (interactive) (ispell-pdict-save t t)))) 838 '(menu-item "Save Dictionary"
839 (lambda ()(interactive) (ispell-pdict-save t t))
840 :help "Save personal dictionary"))
841 (define-key ispell-menu-map [ispell-help]
842 ;; use (x-popup-menu last-nonmenu-event(list "" ispell-help-list)) ?
843 '(menu-item
844 "Help"
845 (lambda () (interactive) (describe-function 'ispell-help))
846 :help "Show standard Ispell keybindings and commands"))
800 (define-key ispell-menu-map [ispell-complete-word] 847 (define-key ispell-menu-map [ispell-complete-word]
801 '("Complete Word" . ispell-complete-word)) 848 '(menu-item "Complete Word" ispell-complete-word
849 :help "Complete word at cursor using dictionary"))
802 (define-key ispell-menu-map [ispell-complete-word-interior-frag] 850 (define-key ispell-menu-map [ispell-complete-word-interior-frag]
803 '("Complete Word Frag" . ispell-complete-word-interior-frag)))) 851 '(menu-item "Complete Word Fragment" ispell-complete-word-interior-frag
852 :help "Complete word fragment at cursor"))))
804 853
805 ;;;###autoload 854 ;;;###autoload
806 (if ispell-menu-map-needed 855 (if ispell-menu-map-needed
807 (progn 856 (progn
808 (define-key ispell-menu-map [ispell-continue] 857 (define-key ispell-menu-map [ispell-continue]
809 '("Continue Check" . ispell-continue)) 858 '(menu-item "Continue Spell-Checking" ispell-continue
859 :enable (and (boundp 'ispell-region-end)
860 (marker-position ispell-region-end)
861 (equal (marker-buffer ispell-region-end)
862 (current-buffer)))))
810 (define-key ispell-menu-map [ispell-word] 863 (define-key ispell-menu-map [ispell-word]
811 '("Check Word" . ispell-word)) 864 '(menu-item "Spell-Check Word" ispell-word
865 :help "Spell-check word at cursor"))
812 (define-key ispell-menu-map [ispell-comments-and-strings] 866 (define-key ispell-menu-map [ispell-comments-and-strings]
813 '("Check Comments" . ispell-comments-and-strings)) 867 '(menu-item "Spell-Check Comments" ispell-comments-and-strings
814 (define-key ispell-menu-map [ispell-region] 868 :help "Spell-check only comments and strings"))))
815 '("Check Region" . ispell-region))
816 (define-key ispell-menu-map [ispell-buffer]
817 '("Check Buffer" . ispell-buffer))))
818 869
819 ;;;###autoload 870 ;;;###autoload
820 (if ispell-menu-map-needed 871 (if ispell-menu-map-needed
821 (progn 872 (progn
873 (define-key ispell-menu-map [ispell-region]
874 '(menu-item "Spell-Check Region" ispell-region
875 :enable mark-active
876 :help "Spell-check text in marked region"))
822 (define-key ispell-menu-map [ispell-message] 877 (define-key ispell-menu-map [ispell-message]
823 '("Check Message" . ispell-message)) 878 '(menu-item "Spell-Check Message" ispell-message
824 (define-key ispell-menu-map [ispell-help] 879 :help "Skip headers and included message text"))
825 ;; use (x-popup-menu last-nonmenu-event(list "" ispell-help-list)) ? 880 (define-key ispell-menu-map [ispell-buffer]
826 '("Help" . (lambda () (interactive) (describe-function 'ispell-help)))) 881 '(menu-item "Spell-Check Buffer" ispell-buffer))
827 (put 'ispell-region 'menu-enable 'mark-active)
828 (fset 'ispell-menu-map (symbol-value 'ispell-menu-map)))) 882 (fset 'ispell-menu-map (symbol-value 'ispell-menu-map))))
829 883
830 ;;; XEmacs versions 19 & 20 884 ;;; XEmacs versions 19 & 20
831 (if (and ispell-xemacsp 885 (if (and xemacsp
832 (not ispell-version18p) 886 (not version18p)
833 (featurep 'menubar) 887 (featurep 'menubar)
834 (null ispell-menu-xemacs) 888 (null ispell-menu-xemacs)
835 (not (and (boundp 'infodock-version) infodock-version))) 889 (not (and (boundp 'infodock-version) infodock-version)))
836 (let ((dicts (cons (cons "default" nil) ispell-dictionary-alist)) 890 (let ((dicts (cons (cons "default" nil) ispell-dictionary-alist))
837 (current-menubar (or current-menubar default-menubar)) 891 (current-menubar (or current-menubar default-menubar))
878 (progn 932 (progn
879 (delete-menu-item '("Edit" "Spell")) ; in case already defined 933 (delete-menu-item '("Edit" "Spell")) ; in case already defined
880 (add-menu '("Edit") "Spell" ispell-menu-xemacs))))) 934 (add-menu '("Edit") "Spell" ispell-menu-xemacs)))))
881 935
882 ;;; Allow incrementing characters as integers in XEmacs 20 936 ;;; Allow incrementing characters as integers in XEmacs 20
883 (if (and ispell-xemacsp 937 (if (and xemacsp
884 (fboundp 'int-char)) 938 (fboundp 'int-char))
885 (fset 'ispell-int-char 'int-char) 939 (fset 'ispell-int-char 'int-char)
886 ;; Emacs and XEmacs 19 or earlier 940 ;; Emacs and XEmacs 19 or earlier
887 (fset 'ispell-int-char 'identity)) 941 (fset 'ispell-int-char 'identity))
888 942
889 943
890 ;;; **********************************************************************
891 ;;; The following are used by ispell, and should not be changed.
892 ;;; ********************************************************************** 944 ;;; **********************************************************************
893 945
894 946
895 ;;; This variable contains the current dictionary being used if the ispell 947 ;;; This variable contains the current dictionary being used if the ispell
896 ;;; process is running. Otherwise it contains the global default. 948 ;;; process is running. Otherwise it contains the global default.
903 used as key in `ispell-dictionary-alist' (which see).") 955 used as key in `ispell-dictionary-alist' (which see).")
904 956
905 (defun ispell-decode-string (str) 957 (defun ispell-decode-string (str)
906 "Decodes multibyte character strings. 958 "Decodes multibyte character strings.
907 Protects against bogus binding of `enable-multibyte-characters' in XEmacs." 959 Protects against bogus binding of `enable-multibyte-characters' in XEmacs."
908 (if (and (or ispell-xemacsp 960 (if (and (or xemacsp
909 (and (boundp 'enable-multibyte-characters) 961 (and (boundp 'enable-multibyte-characters)
910 enable-multibyte-characters)) 962 enable-multibyte-characters))
911 (fboundp 'decode-coding-string) 963 (fboundp 'decode-coding-string)
912 (ispell-get-coding-system)) 964 (ispell-get-coding-system))
913 (decode-coding-string str (ispell-get-coding-system)) 965 (decode-coding-string str (ispell-get-coding-system))
932 (nth 7 (assoc ispell-dictionary ispell-dictionary-alist))) 984 (nth 7 (assoc ispell-dictionary ispell-dictionary-alist)))
933 985
934 (defvar ispell-process nil 986 (defvar ispell-process nil
935 "The process object for Ispell.") 987 "The process object for Ispell.")
936 988
989 (defvar ispell-async-processp (and (fboundp 'kill-process)
990 (fboundp 'process-send-string)
991 (fboundp 'accept-process-output)
992 ;;(fboundp 'start-process)
993 ;;(fboundp 'set-process-filter)
994 ;;(fboundp 'process-kill-without-query)
995 )
996 "Non-nil means that the OS supports asynchronous processes.")
997
937 (defvar ispell-pdict-modified-p nil 998 (defvar ispell-pdict-modified-p nil
938 "Non-nil means personal dictionary has modifications to be saved.") 999 "Non-nil means personal dictionary has modifications to be saved.")
939 1000
940 ;;; If you want to save the dictionary when quitting, must do so explicitly. 1001 ;;; If you want to save the dictionary when quitting, must do so explicitly.
941 ;;; When non-nil, the spell session is terminated. 1002 ;;; When non-nil, the spell session is terminated.
942 ;;; When numeric, contains cursor location in buffer, and cursor remains there. 1003 ;;; When numeric, contains cursor location in buffer, and cursor remains there.
943 (defvar ispell-quit nil) 1004 (defvar ispell-quit nil)
944 1005
1006 (defvar ispell-process-directory nil
1007 "The directory where `ispell-process' was started.")
1008
945 (defvar ispell-filter nil 1009 (defvar ispell-filter nil
946 "Output filter from piped calls to Ispell.") 1010 "Output filter from piped calls to Ispell.")
947 1011
948 (defvar ispell-filter-continue nil 1012 (defvar ispell-filter-continue nil
949 "Control variable for Ispell filter function.") 1013 "Control variable for Ispell filter function.")
950 1014
951 (defvar ispell-process-directory nil 1015 (defvar ispell-output-buffer nil
952 "The directory where `ispell-process' was started.") 1016 "Buffer used for reading output of a synchronous Ispell subprocess.")
1017
1018 (defvar ispell-session-buffer nil
1019 "Buffer used for passing input to a synchronous Ispell subprocess.")
1020
1021 (defvar ispell-cmd-args nil
1022 "Command-line arguments to pass to a synchronous Ispell subprocess.")
953 1023
954 (defvar ispell-query-replace-marker (make-marker) 1024 (defvar ispell-query-replace-marker (make-marker)
955 "Marker for `query-replace' processing.") 1025 "Marker for `query-replace' processing.")
956 1026
957 (defvar ispell-recursive-edit-marker (make-marker) 1027 (defvar ispell-recursive-edit-marker (make-marker)
1046 1116
1047 Delete or add any regions you want to be automatically selected 1117 Delete or add any regions you want to be automatically selected
1048 for skipping in latex mode.") 1118 for skipping in latex mode.")
1049 1119
1050 1120
1051 (defcustom ispell-skip-sgml 'use-mode-name
1052 "*Indicates whether ispell should skip spell checking of SGML markup.
1053 If t, always skip SGML markup; if nil, never skip; if non-t and non-nil,
1054 guess whether SGML markup should be skipped according to the name of the
1055 buffer's major mode."
1056 :type '(choice (const :tag "always" t) (const :tag "never" nil)
1057 (const :tag "use-mode-name" use-mode-name))
1058 :group 'ispell)
1059
1060 (defvar ispell-local-pdict ispell-personal-dictionary 1121 (defvar ispell-local-pdict ispell-personal-dictionary
1061 "A buffer local variable containing the current personal dictionary. 1122 "A buffer local variable containing the current personal dictionary.
1062 If non-nil, the value must be a string, which is a file name. 1123 If non-nil, the value must be a string, which is a file name.
1063 1124
1064 If you specify a personal dictionary for the current buffer which is 1125 If you specify a personal dictionary for the current buffer which is
1093 ;;; ********************************************************************** 1154 ;;; **********************************************************************
1094 ;;; ********************************************************************** 1155 ;;; **********************************************************************
1095 1156
1096 1157
1097 1158
1098 (and (not ispell-version18p)
1099 (not (boundp 'epoch::version))
1100 (defalias 'ispell 'ispell-buffer)
1101 (defalias 'ispell-check-version 'check-ispell-version))
1102
1103
1104 (if (not (fboundp 'buffer-substring-no-properties))
1105 (defun buffer-substring-no-properties (start end)
1106 (buffer-substring start end)))
1107
1108 ;;;###autoload 1159 ;;;###autoload
1109 (define-key esc-map "$" 'ispell-word) 1160 (define-key esc-map "$" 'ispell-word)
1161
1162
1163 (defun ispell-accept-output (&optional timeout-secs timeout-msecs)
1164 "Wait for output from ispell process, or TIMEOUT-SECS and TIMEOUT-MSECS.
1165 If asynchronous subprocesses are not supported, call `ispell-filter' and
1166 pass it the output of the last ispell invocation."
1167 (if ispell-async-processp
1168 (accept-process-output ispell-process timeout-secs timeout-msecs)
1169 (if (null ispell-process)
1170 (error "No Ispell process to read output from!")
1171 (let ((buf ispell-output-buffer)
1172 ispell-output)
1173 (if (not (bufferp buf))
1174 (setq ispell-filter nil)
1175 (save-excursion
1176 (set-buffer buf)
1177 (setq ispell-output (buffer-substring-no-properties
1178 (point-min) (point-max))))
1179 (ispell-filter t ispell-output)
1180 (save-excursion
1181 (set-buffer buf)
1182 (erase-buffer)))))))
1183
1184
1185 (defun ispell-send-string (string)
1186 "Send the string STRING to the Ispell process."
1187 (if ispell-async-processp
1188 (process-send-string ispell-process string)
1189 ;; Asynchronous subprocesses aren't supported on this losing system.
1190 ;; We keep all the directives passed to Ispell during the entire
1191 ;; session in a buffer, and pass them anew each time we invoke
1192 ;; Ispell to process another chunk of text. (Yes, I know this is a
1193 ;; terrible kludge, and it's a bit slow, but it does get the work done.)
1194 (let ((cmd (aref string 0))
1195 ;; The following commands are not passed to Ispell until
1196 ;; we have a *reall* reason to invoke it.
1197 (cmds-to-defer '(?* ?@ ?~ ?+ ?- ?! ?%))
1198 (default-major-mode 'fundamental-mode)
1199 (session-buf ispell-session-buffer)
1200 (output-buf ispell-output-buffer)
1201 (ispell-args ispell-cmd-args)
1202 (defdir ispell-process-directory)
1203 prev-pos)
1204 (save-excursion
1205 (set-buffer session-buf)
1206 (setq prev-pos (point))
1207 (setq default-directory defdir)
1208 (insert string)
1209 (if (not (memq cmd cmds-to-defer))
1210 (let (coding-system-for-read coding-system-for-write status)
1211 (if (or xemacsp
1212 (and (boundp 'enable-multibyte-characters)
1213 enable-multibyte-characters))
1214 (setq coding-system-for-read (ispell-get-coding-system)
1215 coding-system-for-write (ispell-get-coding-system)))
1216 (set-buffer output-buf)
1217 (erase-buffer)
1218 (set-buffer session-buf)
1219 (setq status
1220 (apply 'call-process-region (point-min) (point-max)
1221 ispell-program-name nil
1222 output-buf nil
1223 "-a" "-m" ispell-args))
1224 (set-buffer output-buf)
1225 (goto-char (point-min))
1226 (save-match-data
1227 (if (not (looking-at "@(#) "))
1228 (error "Ispell error: %s"
1229 (buffer-substring-no-properties
1230 (point) (progn (end-of-line) (point)))))
1231 ;; If STRING is "^Z\n", we just started Ispell and need
1232 ;; to retain its version ID line in the output buffer.
1233 ;; Otherwise, remove the ID line, as it will confuse
1234 ;; `ispell-filter'.
1235 (or (string= string "\032\n")
1236 (progn
1237 (forward-line)
1238 (delete-region (point-min) (point))))
1239 ;; If STRING begins with ^ or any normal character, we need
1240 ;; to remove the last line from the session buffer, since it
1241 ;; was just spell-checked, and we don't want to check it again.
1242 ;; The same goes for the # command, since Ispell already saved
1243 ;; the personal dictionary.
1244 (set-buffer session-buf)
1245 (delete-region prev-pos (point))
1246 ;; Ispell run synchronously saves the personal dictionary
1247 ;; after each successful command. So we can remove any
1248 ;; lines in the session buffer that insert words into the
1249 ;; dictionary.
1250 (if (memq status '(0 nil))
1251 (let ((more-lines t))
1252 (goto-char (point-min))
1253 (while more-lines
1254 (if (looking-at "^\\*")
1255 (let ((start (point)))
1256 (forward-line)
1257 (delete-region start (point)))
1258 (setq more-lines (= 0 (forward-line))))))))))))))
1259
1260
1110 1261
1111 ;;;###autoload 1262 ;;;###autoload
1112 (defun ispell-word (&optional following quietly continue) 1263 (defun ispell-word (&optional following quietly continue)
1113 "Check spelling of word under or before the cursor. 1264 "Check spelling of word under or before the cursor.
1114 If the word is not found in dictionary, display possible corrections 1265 If the word is not found in dictionary, display possible corrections
1154 (cond 1305 (cond
1155 ((> (length word) 2) 1306 ((> (length word) 2)
1156 (or quietly 1307 (or quietly
1157 (message "Checking spelling of %s..." 1308 (message "Checking spelling of %s..."
1158 (funcall ispell-format-word word))) 1309 (funcall ispell-format-word word)))
1159 (process-send-string ispell-process "%\n") ;put in verbose mode 1310 (ispell-send-string "%\n") ; put in verbose mode
1160 (process-send-string ispell-process (concat "^" word "\n")) 1311 (ispell-send-string (concat "^" word "\n"))
1161 ;; wait until ispell has processed word 1312 ;; wait until ispell has processed word
1162 (while (progn 1313 (while (progn
1163 (accept-process-output ispell-process) 1314 (ispell-accept-output)
1164 (not (string= "" (car ispell-filter))))) 1315 (not (string= "" (car ispell-filter)))))
1165 ;;(process-send-string ispell-process "!\n") ;back to terse mode. 1316 ;;(ispell-send-string "!\n") ;back to terse mode.
1166 (setq ispell-filter (cdr ispell-filter)) ; remove extra \n 1317 (setq ispell-filter (cdr ispell-filter)) ; remove extra \n
1167 (if (and ispell-filter (listp ispell-filter)) 1318 (if (and ispell-filter (listp ispell-filter))
1168 (if (> (length ispell-filter) 1) 1319 (if (> (length ispell-filter) 1)
1169 (error "Ispell and its process have different character maps.") 1320 (error "Ispell and its process have different character maps.")
1170 (setq poss (ispell-parse-output (car ispell-filter))))) 1321 (setq poss (ispell-parse-output (car ispell-filter)))))
1294 (if (and ispell-pdict-modified-p (listp ispell-pdict-modified-p)) 1445 (if (and ispell-pdict-modified-p (listp ispell-pdict-modified-p))
1295 (setq ispell-pdict-modified-p (car ispell-pdict-modified-p))) 1446 (setq ispell-pdict-modified-p (car ispell-pdict-modified-p)))
1296 (if (or ispell-pdict-modified-p force-save) 1447 (if (or ispell-pdict-modified-p force-save)
1297 (if (or no-query (y-or-n-p "Personal dictionary modified. Save? ")) 1448 (if (or no-query (y-or-n-p "Personal dictionary modified. Save? "))
1298 (progn 1449 (progn
1299 (process-send-string ispell-process "#\n") ; save dictionary 1450 (ispell-send-string "#\n") ; save dictionary
1300 (message "Personal dictionary saved.")))) 1451 (message "Personal dictionary saved."))))
1301 ;; unassert variable, even if not saved to avoid questioning. 1452 ;; unassert variable, even if not saved to avoid questioning.
1302 (setq ispell-pdict-modified-p nil)) 1453 (setq ispell-pdict-modified-p nil))
1303 1454
1304 1455
1367 (insert "(" count ") " (car choices) " ") 1518 (insert "(" count ") " (car choices) " ")
1368 (setq choices (cdr choices) 1519 (setq choices (cdr choices)
1369 count (ispell-int-char (1+ count)))) 1520 count (ispell-int-char (1+ count))))
1370 (setq count (ispell-int-char (- count ?0 skipped)))) 1521 (setq count (ispell-int-char (- count ?0 skipped))))
1371 1522
1372 ;; Assure word is visible 1523 ;; ensure word is visible
1373 (if (not (pos-visible-in-window-p end)) 1524 (if (not (pos-visible-in-window-p end))
1374 (sit-for 0)) 1525 (sit-for 0))
1375 1526
1376 ;; allow temporary split of dedicated windows... 1527 ;; allow temporary split of dedicated windows...
1377 (if dedicated 1528 (if dedicated
1416 (setq num (- char ?0 skipped))) 1567 (setq num (- char ?0 skipped)))
1417 1568
1418 (cond 1569 (cond
1419 ((= char ? ) nil) ; accept word this time only 1570 ((= char ? ) nil) ; accept word this time only
1420 ((= char ?i) ; accept and insert word into pers dict 1571 ((= char ?i) ; accept and insert word into pers dict
1421 (process-send-string ispell-process (concat "*" word "\n")) 1572 (ispell-send-string (concat "*" word "\n"))
1422 (setq ispell-pdict-modified-p '(t)) ; dictionary modified! 1573 (setq ispell-pdict-modified-p '(t)) ; dictionary modified!
1423 nil) 1574 nil)
1424 ((or (= char ?a) (= char ?A)) ; accept word without insert 1575 ((or (= char ?a) (= char ?A)) ; accept word without insert
1425 (process-send-string ispell-process (concat "@" word "\n")) 1576 (ispell-send-string (concat "@" word "\n"))
1426 (if (null ispell-pdict-modified-p) 1577 (if (null ispell-pdict-modified-p)
1427 (setq ispell-pdict-modified-p 1578 (setq ispell-pdict-modified-p
1428 (list ispell-pdict-modified-p))) 1579 (list ispell-pdict-modified-p)))
1429 (if (= char ?A) 0)) ; return 0 for ispell-add buffer-local 1580 (if (= char ?A) 0)) ; return 0 for ispell-add buffer-local
1430 ((or (= char ?r) (= char ?R)) ; type in replacement 1581 ((or (= char ?r) (= char ?R)) ; type in replacement
1516 (and (eq 'block ispell-highlight-p) 1667 (and (eq 'block ispell-highlight-p)
1517 (ispell-highlight-spelling-error start end nil 1668 (ispell-highlight-spelling-error start end nil
1518 'block)) 1669 'block))
1519 t) ; reselect from new choices 1670 t) ; reselect from new choices
1520 ((= char ?u) ; insert lowercase into dictionary 1671 ((= char ?u) ; insert lowercase into dictionary
1521 (process-send-string ispell-process 1672 (ispell-send-string (concat "*" (downcase word) "\n"))
1522 (concat "*" (downcase word) "\n"))
1523 (setq ispell-pdict-modified-p '(t)) ; dictionary modified! 1673 (setq ispell-pdict-modified-p '(t)) ; dictionary modified!
1524 nil) 1674 nil)
1525 ((= char ?m) ; type in what to insert 1675 ((= char ?m) ; type in what to insert
1526 (process-send-string 1676 (ispell-send-string
1527 ispell-process (concat "*" (read-string "Insert: " word) 1677 (concat "*" (read-string "Insert: " word) "\n"))
1528 "\n"))
1529 (setq ispell-pdict-modified-p '(t)) 1678 (setq ispell-pdict-modified-p '(t))
1530 (cons word nil)) 1679 (cons word nil))
1531 ((and (>= num 0) (< num count)) 1680 ((and (>= num 0) (< num count))
1532 (if ispell-query-replace-choices ; Query replace flag 1681 (if ispell-query-replace-choices ; Query replace flag
1533 (list (nth num miss) 'query-replace) 1682 (list (nth num miss) 'query-replace)
1679 (help-3 (concat "[u]ncapitalized insert into dict. " 1828 (help-3 (concat "[u]ncapitalized insert into dict. "
1680 "Type 'x C-h d ispell-help' for more help"))) 1829 "Type 'x C-h d ispell-help' for more help")))
1681 (save-window-excursion 1830 (save-window-excursion
1682 (if ispell-help-in-bufferp 1831 (if ispell-help-in-bufferp
1683 (progn 1832 (progn
1684 (ispell-overlay-window (if ispell-xemacsp 5 4)) 1833 (ispell-overlay-window (if xemacsp 5 4))
1685 (switch-to-buffer (get-buffer-create "*Ispell Help*")) 1834 (switch-to-buffer (get-buffer-create "*Ispell Help*"))
1686 (insert (concat help-1 "\n" help-2 "\n" help-3)) 1835 (insert (concat help-1 "\n" help-2 "\n" help-3))
1687 (sit-for 5) 1836 (sit-for 5)
1688 (kill-buffer "*Ispell Help*")) 1837 (kill-buffer "*Ispell Help*"))
1689 (select-window (minibuffer-window)) 1838 (select-window (minibuffer-window))
1690 (erase-buffer) 1839 (erase-buffer)
1691 (if (not ispell-version18p) (message nil)) 1840 (if (not version18p) (message nil))
1692 ;;(set-minibuffer-window (selected-window)) 1841 ;;(set-minibuffer-window (selected-window))
1693 (enlarge-window 2) 1842 (enlarge-window 2)
1694 (insert (concat help-1 "\n" help-2 "\n" help-3)) 1843 (insert (concat help-1 "\n" help-2 "\n" help-3))
1695 (sit-for 5) 1844 (sit-for 5)
1696 (erase-buffer)))))) 1845 (erase-buffer))))))
1854 (delete-overlay ispell-overlay))) 2003 (delete-overlay ispell-overlay)))
1855 2004
1856 2005
1857 (defun ispell-highlight-spelling-error (start end &optional highlight refresh) 2006 (defun ispell-highlight-spelling-error (start end &optional highlight refresh)
1858 (cond 2007 (cond
1859 (ispell-xemacsp 2008 (xemacsp
1860 (ispell-highlight-spelling-error-xemacs start end highlight)) 2009 (ispell-highlight-spelling-error-xemacs start end highlight))
1861 ((and (not ispell-version18p) 2010 ((and (not version18p)
1862 (featurep 'faces) window-system) 2011 (featurep 'faces) window-system)
1863 (ispell-highlight-spelling-error-overlay start end highlight)) 2012 (ispell-highlight-spelling-error-overlay start end highlight))
1864 (t (ispell-highlight-spelling-error-generic start end highlight refresh)))) 2013 (t (ispell-highlight-spelling-error-generic start end highlight refresh))))
1865 2014
1866 2015
1940 (list original-word 2089 (list original-word
1941 (if (numberp shift) (+ shift offset) offset) 2090 (if (numberp shift) (+ shift offset) offset)
1942 (nreverse miss-list) (nreverse guess-list))))))) 2091 (nreverse miss-list) (nreverse guess-list)))))))
1943 2092
1944 2093
2094 (defun ispell-process-status ()
2095 "Return the status of the Ispell process.
2096 When asynchronous processes are not supported, `run' is always returned."
2097 (if ispell-async-processp
2098 (process-status ispell-process)
2099 (and ispell-process 'run)))
2100
2101
2102 (defun ispell-start-process ()
2103 "Start the ispell process, with support for no asynchronous processes.
2104 Keeps argument list for future ispell invocations for no async support."
2105 (let (args)
2106 ;; Local dictionary becomes the global dictionary in use.
2107 (if ispell-local-dictionary
2108 (setq ispell-dictionary ispell-local-dictionary))
2109 (setq args (ispell-get-ispell-args))
2110 (if ispell-dictionary ; use specified dictionary
2111 (setq args
2112 (append (list "-d" ispell-dictionary) args)))
2113 (if ispell-personal-dictionary ; use specified pers dict
2114 (setq args
2115 (append args
2116 (list "-p"
2117 (expand-file-name ispell-personal-dictionary)))))
2118 (setq args (append args ispell-extra-args))
2119
2120 (if ispell-async-processp
2121 (let ((process-connection-type ispell-use-ptys-p))
2122 (apply 'start-process
2123 "ispell" nil ispell-program-name
2124 "-a" ; accept single input lines
2125 "-m" ; make root/affix combos not in dict
2126 args))
2127 (setq ispell-cmd-args args
2128 ispell-output-buffer (generate-new-buffer " *ispell-output*")
2129 ispell-session-buffer (generate-new-buffer " *ispell-session*"))
2130 (ispell-send-string "\032\n") ; so Ispell prints version and exits
2131 t)))
2132
2133
2134
1945 (defun ispell-init-process () 2135 (defun ispell-init-process ()
1946 "Check status of Ispell process and start if necessary." 2136 "Check status of Ispell process and start if necessary."
1947 (if (and ispell-process 2137 (if (and ispell-process
1948 (eq (process-status ispell-process) 'run) 2138 (eq (ispell-process-status) 'run)
1949 ;; If we're using a personal dictionary, assure 2139 ;; If we're using a personal dictionary, assure
1950 ;; we're in the same default directory! 2140 ;; we're in the same default directory!
1951 (or (not ispell-personal-dictionary) 2141 (or (not ispell-personal-dictionary)
1952 (equal ispell-process-directory default-directory))) 2142 (equal ispell-process-directory default-directory)))
1953 (setq ispell-filter nil ispell-filter-continue nil) 2143 (setq ispell-filter nil ispell-filter-continue nil)
1954 ;; may need to restart to select new personal dictionary. 2144 ;; may need to restart to select new personal dictionary.
1955 (ispell-kill-ispell t) 2145 (ispell-kill-ispell t)
1956 (message "Starting new Ispell process...") 2146 (message "Starting new Ispell process...")
1957 (sit-for 0) 2147 (sit-for 0)
1958 (check-ispell-version) 2148 (check-ispell-version)
1959 (setq ispell-process 2149 (setq ispell-process-directory default-directory
1960 (let ((process-connection-type ispell-use-ptys-p)) 2150 ispell-process (ispell-start-process)
1961 (apply 'start-process
1962 "ispell" nil ispell-program-name
1963 "-a" ; accept single input lines
1964 "-m" ; make root/affix combos not in dict
1965 (let (args)
1966 ;; Local dictionary becomes the global dictionary in use.
1967 (if ispell-local-dictionary
1968 (setq ispell-dictionary ispell-local-dictionary))
1969 (setq args (ispell-get-ispell-args))
1970 (if ispell-dictionary ; use specified dictionary
1971 (setq args
1972 (append (list "-d" ispell-dictionary) args)))
1973 (if ispell-personal-dictionary ; use specified pers dict
1974 (setq args
1975 (append args
1976 (list "-p"
1977 (expand-file-name
1978 ispell-personal-dictionary)))))
1979 (setq args (append args ispell-extra-args))
1980 args)))
1981 ispell-filter nil 2151 ispell-filter nil
1982 ispell-filter-continue nil 2152 ispell-filter-continue nil)
1983 ispell-process-directory default-directory) 2153 (if ispell-async-processp
1984 (set-process-filter ispell-process 'ispell-filter) 2154 (set-process-filter ispell-process 'ispell-filter))
1985 ;; protect against bogus binding of `enable-multibyte-characters' in XEmacs 2155 ;; protect against bogus binding of `enable-multibyte-characters' in XEmacs
1986 (if (and (or ispell-xemacsp 2156 (if (and (or xemacsp
1987 (and (boundp 'enable-multibyte-characters) 2157 (and (boundp 'enable-multibyte-characters)
1988 enable-multibyte-characters)) 2158 enable-multibyte-characters))
1989 (fboundp 'set-process-coding-system)) 2159 (fboundp 'set-process-coding-system))
1990 (set-process-coding-system ispell-process (ispell-get-coding-system) 2160 (set-process-coding-system ispell-process (ispell-get-coding-system)
1991 (ispell-get-coding-system))) 2161 (ispell-get-coding-system)))
1992 ;; Get version ID line 2162 ;; Get version ID line
1993 (if (not ispell-version18p) 2163 (if (not version18p)
1994 (accept-process-output ispell-process 3) 2164 (ispell-accept-output 3)
1995 (accept-process-output ispell-process)) 2165 (ispell-accept-output))
1996 ;; get more output if filter empty? 2166 ;; get more output if filter empty?
1997 (if (null ispell-filter) (accept-process-output ispell-process 3)) 2167 (if (null ispell-filter) (ispell-accept-output 3))
1998 (cond ((null ispell-filter) 2168 (cond ((null ispell-filter)
1999 (error "%s did not output version line" ispell-program-name)) 2169 (error "%s did not output version line" ispell-program-name))
2000 ((and 2170 ((and
2001 (stringp (car ispell-filter)) 2171 (stringp (car ispell-filter))
2002 (if (string-match "warning: " (car ispell-filter)) 2172 (if (string-match "warning: " (car ispell-filter))
2003 (progn 2173 (progn
2004 (if (not ispell-version18p) 2174 (if (not version18p)
2005 (accept-process-output ispell-process 3) ; was warn msg. 2175 (ispell-accept-output 3) ; was warn msg.
2006 (accept-process-output ispell-process)) 2176 (ispell-accept-output))
2007 (stringp (car ispell-filter))) 2177 (stringp (car ispell-filter)))
2008 (null (cdr ispell-filter))) 2178 (null (cdr ispell-filter)))
2009 (string-match "^@(#) " (car ispell-filter))) 2179 (string-match "^@(#) " (car ispell-filter)))
2010 ;; got the version line as expected (we already know it's the right 2180 ;; got the version line as expected (we already know it's the right
2011 ;; version, so don't bother checking again.) 2181 ;; version, so don't bother checking again.)
2013 (t 2183 (t
2014 ;; Otherwise, it must be an error message. Show the user. 2184 ;; Otherwise, it must be an error message. Show the user.
2015 ;; But first wait to see if some more output is going to arrive. 2185 ;; But first wait to see if some more output is going to arrive.
2016 ;; Otherwise we get cool errors like "Can't open ". 2186 ;; Otherwise we get cool errors like "Can't open ".
2017 (sleep-for 1) 2187 (sleep-for 1)
2018 (accept-process-output ispell-process 3) 2188 (ispell-accept-output 3)
2019 (error "%s" (mapconcat 'identity ispell-filter "\n")))) 2189 (error "%s" (mapconcat 'identity ispell-filter "\n"))))
2020 (setq ispell-filter nil) ; Discard version ID line 2190 (setq ispell-filter nil) ; Discard version ID line
2021 (let ((extended-char-mode (ispell-get-extended-character-mode))) 2191 (let ((extended-char-mode (ispell-get-extended-character-mode)))
2022 (if extended-char-mode ; ~ extended character mode 2192 (if extended-char-mode ; ~ extended character mode
2023 (process-send-string ispell-process 2193 (ispell-send-string (concat extended-char-mode "\n"))))
2024 (concat extended-char-mode "\n")))) 2194 (if ispell-async-processp
2025 (process-kill-without-query ispell-process))) 2195 (process-kill-without-query ispell-process))))
2026 2196
2027 ;;;###autoload 2197 ;;;###autoload
2028 (defun ispell-kill-ispell (&optional no-error) 2198 (defun ispell-kill-ispell (&optional no-error)
2029 "Kill current Ispell process (so that you may start a fresh one). 2199 "Kill current Ispell process (so that you may start a fresh one).
2030 With NO-ERROR, just return non-nil if there was no Ispell running." 2200 With NO-ERROR, just return non-nil if there was no Ispell running."
2031 (interactive) 2201 (interactive)
2032 (if (not (and ispell-process 2202 (if (not (and ispell-process
2033 (eq (process-status ispell-process) 'run))) 2203 (eq (ispell-process-status) 'run)))
2034 (or no-error 2204 (or no-error
2035 (error "There is no ispell process running!")) 2205 (error "There is no ispell process running!"))
2036 (process-send-eof ispell-process) 2206 (if ispell-async-processp
2037 (if (eq (process-status ispell-process) 'run) 2207 (progn
2038 (accept-process-output ispell-process 1)) 2208 (process-send-eof ispell-process)
2039 (if (eq (process-status ispell-process) 'run) 2209 (if (eq (ispell-process-status) 'run)
2040 (kill-process ispell-process)) 2210 (ispell-accept-output 1))
2041 (while (not (or (eq (process-status ispell-process) 'exit) 2211 (if (eq (ispell-process-status) 'run)
2042 (eq (process-status ispell-process) 'signal))) 2212 (kill-process ispell-process))
2043 (if ispell-version20p (sleep-for 0.25) 2213 (while (not (or (eq (ispell-process-status) 'exit)
2044 (sleep-for 0 250))) 2214 (eq (ispell-process-status) 'signal)))
2215 (if (or xemacsp version20p) (sleep-for 0.25)
2216 (sleep-for 0 250))))
2217 ;; synchronous processes
2218 (ispell-send-string "\n") ; make sure side effects occurred.
2219 (kill-buffer ispell-output-buffer)
2220 (kill-buffer ispell-session-buffer)
2221 (setq ispell-output-buffer nil
2222 ispell-session-buffer nil))
2045 (setq ispell-process nil) 2223 (setq ispell-process nil)
2046 (message "Ispell process killed") 2224 (message "Ispell process killed")
2047 nil)) 2225 nil))
2048 2226
2049 2227
2354 ;;(declare special start end) 2532 ;;(declare special start end)
2355 (let (poss accept-list) 2533 (let (poss accept-list)
2356 (if (not (numberp shift)) 2534 (if (not (numberp shift))
2357 (setq shift 0)) 2535 (setq shift 0))
2358 ;; send string to spell process and get input. 2536 ;; send string to spell process and get input.
2359 (process-send-string ispell-process string) 2537 (ispell-send-string string)
2360 (while (progn 2538 (while (progn
2361 (accept-process-output ispell-process) 2539 (ispell-accept-output)
2362 ;; Last item of output contains a blank line. 2540 ;; Last item of output contains a blank line.
2363 (not (string= "" (car ispell-filter))))) 2541 (not (string= "" (car ispell-filter)))))
2364 ;; parse all inputs from the stream one word at a time. 2542 ;; parse all inputs from the stream one word at a time.
2365 ;; Place in FIFO order and remove the blank item. 2543 ;; Place in FIFO order and remove the blank item.
2366 (setq ispell-filter (nreverse (cdr ispell-filter))) 2544 (setq ispell-filter (nreverse (cdr ispell-filter)))
2424 "Don't start query replace on a line with math characters" 2602 "Don't start query replace on a line with math characters"
2425 ) 2603 )
2426 (set-marker line-end (point)) 2604 (set-marker line-end (point))
2427 (setq ispell-filter nil 2605 (setq ispell-filter nil
2428 recheck-region t))) 2606 recheck-region t)))
2429 2607
2430 ;; insert correction if needed 2608 ;; insert correction if needed
2431 (cond 2609 (cond
2432 ((or (null replace) 2610 ((or (null replace)
2433 (equal 0 replace)) ; ACCEPT/INSERT 2611 (equal 0 replace)) ; ACCEPT/INSERT
2434 (if (equal 0 replace) ; BUFFER-LOCAL DICT ADD 2612 (if (equal 0 replace) ; BUFFER-LOCAL DICT ADD
2850 (defun ispell-buffer-local-parsing () 3028 (defun ispell-buffer-local-parsing ()
2851 "Place Ispell into parsing mode for this buffer. 3029 "Place Ispell into parsing mode for this buffer.
2852 Overrides the default parsing mode. 3030 Overrides the default parsing mode.
2853 Includes Latex/Nroff modes and extended character mode." 3031 Includes Latex/Nroff modes and extended character mode."
2854 ;; (ispell-init-process) must already be called. 3032 ;; (ispell-init-process) must already be called.
2855 (process-send-string ispell-process "!\n") ; Put process in terse mode. 3033 (ispell-send-string "!\n") ; Put process in terse mode.
2856 ;; We assume all major modes with "tex-mode" in them should use latex parsing 3034 ;; We assume all major modes with "tex-mode" in them should use latex parsing
2857 ;; When exclusively checking comments, set to raw text mode (nroff). 3035 ;; When exclusively checking comments, set to raw text mode (nroff).
2858 (if (and (not (eq 'exclusive ispell-check-comments)) 3036 (if (and (not (eq 'exclusive ispell-check-comments))
2859 (or (and (eq ispell-parser 'use-mode-name) 3037 (or (and (eq ispell-parser 'use-mode-name)
2860 (string-match "[Tt][Ee][Xx]-mode" 3038 (string-match "[Tt][Ee][Xx]-mode"
2861 (symbol-name major-mode))) 3039 (symbol-name major-mode)))
2862 (eq ispell-parser 'tex))) 3040 (eq ispell-parser 'tex)))
2863 (progn 3041 (progn
2864 (process-send-string ispell-process "+\n") ; set ispell mode to tex 3042 (ispell-send-string "+\n") ; set ispell mode to tex
2865 (if (not (eq ispell-parser 'tex)) 3043 (if (not (eq ispell-parser 'tex))
2866 (set (make-local-variable 'ispell-parser) 'tex))) 3044 (set (make-local-variable 'ispell-parser) 'tex)))
2867 (process-send-string ispell-process "-\n")) ; set mode to normal (nroff) 3045 (ispell-send-string "-\n")) ; set mode to normal (nroff)
2868 ;; If needed, test for SGML & HTML modes and set a buffer local nil/t value. 3046 ;; If needed, test for SGML & HTML modes and set a buffer local nil/t value.
2869 (if (and ispell-skip-sgml (not (eq ispell-skip-sgml t))) 3047 (if (and ispell-skip-sgml (not (eq ispell-skip-sgml t)))
2870 (set (make-local-variable 'ispell-skip-sgml) 3048 (set (make-local-variable 'ispell-skip-sgml)
2871 (not (null (string-match "sgml\\|html" 3049 (not (null (string-match "sgml\\|html"
2872 (downcase (symbol-name major-mode))))))) 3050 (downcase (symbol-name major-mode)))))))
2873 ;; Set default extended character mode for given buffer, if any. 3051 ;; Set default extended character mode for given buffer, if any.
2874 (let ((extended-char-mode (ispell-get-extended-character-mode))) 3052 (let ((extended-char-mode (ispell-get-extended-character-mode)))
2875 (if extended-char-mode 3053 (if extended-char-mode
2876 (process-send-string ispell-process (concat extended-char-mode "\n")))) 3054 (ispell-send-string (concat extended-char-mode "\n"))))
2877 ;; Set buffer-local parsing mode and extended character mode, if specified. 3055 ;; Set buffer-local parsing mode and extended character mode, if specified.
2878 (save-excursion 3056 (save-excursion
2879 (goto-char (point-max)) 3057 (goto-char (point-max))
2880 ;; Uses last occurrence of ispell-parsing-keyword 3058 ;; Uses last occurrence of ispell-parsing-keyword
2881 (if (search-backward ispell-parsing-keyword nil t) 3059 (if (search-backward ispell-parsing-keyword nil t)
2886 ;; space separated definitions. 3064 ;; space separated definitions.
2887 (setq string (downcase (buffer-substring-no-properties 3065 (setq string (downcase (buffer-substring-no-properties
2888 (match-beginning 1) (match-end 1)))) 3066 (match-beginning 1) (match-end 1))))
2889 (cond ((and (string-match "latex-mode" string) 3067 (cond ((and (string-match "latex-mode" string)
2890 (not (eq 'exclusive ispell-check-comments))) 3068 (not (eq 'exclusive ispell-check-comments)))
2891 (process-send-string ispell-process "+\n~tex\n")) 3069 (ispell-send-string "+\n~tex\n"))
2892 ((string-match "nroff-mode" string) 3070 ((string-match "nroff-mode" string)
2893 (process-send-string ispell-process "-\n~nroff\n")) 3071 (ispell-send-string "-\n~nroff\n"))
2894 ((string-match "~" string) ; Set extended character mode. 3072 ((string-match "~" string) ; Set extended character mode.
2895 (process-send-string ispell-process (concat string "\n"))) 3073 (ispell-send-string (concat string "\n")))
2896 (t (message "Invalid Ispell Parsing argument!") 3074 (t (message "Invalid Ispell Parsing argument!")
2897 (sit-for 2)))))))) 3075 (sit-for 2))))))))
2898 3076
2899 3077
2900 ;;; Can kill the current ispell process 3078 ;;; Can kill the current ispell process
2963 (match-end 1))) 3141 (match-end 1)))
2964 ;; This can fail when string contains a word with illegal chars. 3142 ;; This can fail when string contains a word with illegal chars.
2965 ;; Error handling needs to be added between ispell and emacs. 3143 ;; Error handling needs to be added between ispell and emacs.
2966 (if (and (< 1 (length string)) 3144 (if (and (< 1 (length string))
2967 (equal 0 (string-match ispell-casechars string))) 3145 (equal 0 (string-match ispell-casechars string)))
2968 (process-send-string ispell-process 3146 (ispell-send-string (concat "@" string "\n"))))))))
2969 (concat "@" string "\n"))))))))
2970 3147
2971 3148
2972 ;;; returns optionally adjusted region-end-point. 3149 ;;; returns optionally adjusted region-end-point.
2973 3150
2974 (defun ispell-add-per-file-word-list (word) 3151 (defun ispell-add-per-file-word-list (word)