aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard M. Stallman1998-04-30 06:43:48 +0000
committerRichard M. Stallman1998-04-30 06:43:48 +0000
commitf5136913a18bd7415c59dbf7bcaf3c316593c41d (patch)
treeeb02d8a586723ac3085ef3e27e14b7a9919de1fc
parentdcf5e726b5a7f7f7683a7f09d5471273ddcec30d (diff)
downloademacs-f5136913a18bd7415c59dbf7bcaf3c316593c41d.tar.gz
emacs-f5136913a18bd7415c59dbf7bcaf3c316593c41d.zip
Generalized region skipping added.
Checks comments only in code. Added backward compatible support for customize. (ispell-query-replace-choices, ispell-message-dictionary-alist) (ispell-grep-command, ispell-grep-options, ispell-look-command) (ispell-look-options, ispell-use-ptys-p, ispell-local-dictionary) (ispell-dictionary-alist): Now customizable. Fixed type of custom variables: ispell-help-in-bufferp. (ispell-use-framepop-p): New variable. (ispell-dictionary-alist): Added dictionaries: castellano, castellano8 czech, esperanto, esperanto-tex, norsk, russian. Capitalize XEmacs correctly, and change lucid to xemacs in code: (ispell-menu-lucid): Renamed to ispell-menu-xemacs. Changed string compares for version number to be correct for XEmacs. Fixed to work with string properties. (ispell-recursive-edit-marker): new marker saving return point. (ispell-skip-region-alist): New variable defining regions. (ispell-tex-skip-alists): New variable for LaTeX regions. (ispell-skip-sgml): Now buffer-mode aware. (ispell-highlight-p): Support block cursors. (ispell-message-text-end): Don't check signatures. (ispell-comments-and-strings): New command, added to menu. (ispell-int-char): New function for character incrementing. (ispell-word): Produces message on error when called from ispell-minor-mode. Potential infinite loop removed. (ispell-command-loop): prevent XEmacs modeline hiding. Allow temporary split of dedicated windows. Improve recursive edit support. Support block cursors. (ispell-show-choices): New function cleaning up command loop. (ispell-highlight-spelling-error-generic): Block cursor support added. (ispell-highlight-spelling-error-xemacs): Block cursor, name change. (ispell-overlay-window): dedicated window splitting, XEmacs changes. (ispell-parse-output): Displays ispell process error messages. (check-ispell-version): Interactive mode that shows ispell versions. (ispell-begin-skip-region-regexp): New region skipping function. (ispell-begin-tex-skip-regexp): New tex mode region skipping function. (ispell-begin-skip-region): New region skipping function. (ispell-tex-arg-end): New tex mode region skipping function. (ispell-skip-region): New region skipping function. (ispell-get-line): New function to clean up command loop. (ispell-process-line): New function cleaning up command loop. (ispell-continue): Improve recursive editor support. (ispell-complete-word): Interior fragment support improved. (ispell-message): Region skipping vastly improved.
-rw-r--r--lisp/textmodes/ispell.el2108
1 files changed, 1183 insertions, 925 deletions
diff --git a/lisp/textmodes/ispell.el b/lisp/textmodes/ispell.el
index 4d67535b018..8d0e076947f 100644
--- a/lisp/textmodes/ispell.el
+++ b/lisp/textmodes/ispell.el
@@ -1,14 +1,13 @@
1;;; ispell.el --- spell checking using Ispell 1;;; ispell.el --- Interface to International Ispell Version 3.1
2 2
3;; Copyright (C) 1994, 1995, 1997 Free Software Foundation, Inc. 3;; Copyright (C) 1994, 1995, 1997, 1998 Free Software Foundation, Inc.
4 4
5;; Authors : Ken Stevens <k.stevens@ieee.org> 5;; Authors : Ken Stevens <k.stevens@ieee.org>
6;; Last Modified On: Tue Jun 13 12:05:28 EDT 1995 6;; Stevens Mod Date: Tue Apr 28 14:40:01 PDT 1998
7;; Update Revision : 2.37 7;; Stevens Revision: 3.0
8;; Syntax : emacs-lisp 8;; Status : Release with 3.1.12+ ispell.
9;; Status : Release with 3.1.12+ ispell. 9;; Bug Reports : ispell-el-bugs@itcorp.com
10;; Version : International Ispell Version 3.1 by Geoff Kuenning. 10;; Web Site : http://kdstevens.com/~stevens/ispell-page.html
11;; Bug Reports : ispell-el-bugs@itcorp.com
12 11
13;; This file is part of GNU Emacs. 12;; This file is part of GNU Emacs.
14 13
@@ -28,12 +27,12 @@
28;; Boston, MA 02111-1307, USA. 27;; Boston, MA 02111-1307, USA.
29 28
30;; Note: version numbers and time stamp are not updated 29;; Note: version numbers and time stamp are not updated
31;; when this file is edited for release with GNU Emacs. 30;; when this file is edited for release with GNU emacs.
32 31
33;;; Commentary: 32;;; Commentary:
34 33
35;; INSTRUCTIONS 34;; INSTRUCTIONS
36;; 35
37;; This code contains a section of user-settable variables that you should 36;; This code contains a section of user-settable variables that you should
38;; inspect prior to installation. Look past the end of the history list. 37;; inspect prior to installation. Look past the end of the history list.
39;; Set them up for your locale and the preferences of the majority of the 38;; Set them up for your locale and the preferences of the majority of the
@@ -41,41 +40,22 @@
41;; themselves. 40;; themselves.
42;; You particularly may want to change the default dictionary for your 41;; You particularly may want to change the default dictionary for your
43;; country and language. 42;; country and language.
44;; 43
45;;
46;; To fully install this, add this file to your Emacs Lisp directory and
47;; compile it with M-X byte-compile-file. Then add the following to the
48;; appropriate init file:
49;;
50;; (autoload 'ispell-word "ispell"
51;; "Check the spelling of word in buffer." t)
52;; (global-set-key "\e$" 'ispell-word)
53;; (autoload 'ispell-region "ispell"
54;; "Check the spelling of region." t)
55;; (autoload 'ispell-buffer "ispell"
56;; "Check the spelling of buffer." t)
57;; (autoload 'ispell-complete-word "ispell"
58;; "Look up current word in dictionary and try to complete it." t)
59;; (autoload 'ispell-change-dictionary "ispell"
60;; "Change ispell dictionary." t)
61;; (autoload 'ispell-message "ispell"
62;; "Check spelling of mail message or news post.")
63;;
64;; Depending on the mail system you use, you may want to include these: 44;; Depending on the mail system you use, you may want to include these:
65;; 45
66;; (add-hook 'news-inews-hook 'ispell-message) 46;; (add-hook 'news-inews-hook 'ispell-message)
67;; (add-hook 'mail-send-hook 'ispell-message) 47;; (add-hook 'mail-send-hook 'ispell-message)
68;; (add-hook 'mh-before-send-letter-hook 'ispell-message) 48;; (add-hook 'mh-before-send-letter-hook 'ispell-message)
69;; 49
70;; 50
71;; Ispell has a TeX parser and a nroff parser (the default). 51;; Ispell has a TeX parser and a nroff parser (the default).
72;; The parsing is controlled by the variable ispell-parser. Currently 52;; The parsing is controlled by the variable ispell-parser. Currently
73;; it is just a "toggle" between TeX and nroff, but if more parsers are 53;; it is just a "toggle" between TeX and nroff, but if more parsers are
74;; added it will be updated. See the variable description for more info. 54;; added it will be updated. See the variable description for more info.
75;; 55
76;; 56
77;; TABLE OF CONTENTS 57;; TABLE OF CONTENTS
78;; 58
79;; ispell-word 59;; ispell-word
80;; ispell-region 60;; ispell-region
81;; ispell-buffer 61;; ispell-buffer
@@ -87,27 +67,28 @@
87;; ispell-change-dictionary 67;; ispell-change-dictionary
88;; ispell-kill-ispell 68;; ispell-kill-ispell
89;; ispell-pdict-save 69;; ispell-pdict-save
90;; 70;; ispell-skip-region-alist
91;; 71
92;; Commands in ispell-region: 72;; Commands in ispell-region:
93;; Character replacement: Replace word with choice. May query-replace. 73;; Character replacement: Replace word with choice. May query-replace.
94;; ' ': Accept word this time. 74;; ` ': Accept word this time.
95;; 'i': Accept word and insert into private dictionary. 75;; `i': Accept word and insert into private dictionary.
96;; 'a': Accept word for this session. 76;; `a': Accept word for this session.
97;; 'A': Accept word and place in buffer-local dictionary. 77;; `A': Accept word and place in buffer-local dictionary.
98;; 'r': Replace word with typed-in value. Rechecked. 78;; `r': Replace word with typed-in value. Rechecked.
99;; 'R': Replace word with typed-in value. Query-replaced in buffer. Rechecked. 79;; `R': Replace word with typed-in value. Query-replaced in buffer. Rechecked.
100;; '?': Show these commands 80;; `?': Show these commands
101;; 'x': Exit spelling buffer. Move cursor to original point. 81;; `x': Exit spelling buffer. Move cursor to original point.
102;; 'X': Exit spelling buffer. Leave cursor at the current point. 82;; `X': Exit spelling buffer. Leaves cursor at the current point, and permits
103;; 'q': Quit spelling session (Kills ispell process). 83;; the check to be completed later.
104;; 'l': Look up typed-in replacement in alternate dictionary. Wildcards okay. 84;; `q': Quit spelling session (Kills ispell process).
105;; 'u': Like 'i', but the word is lower-cased first. 85;; `l': Look up typed-in replacement in alternate dictionary. Wildcards okay.
106;; 'm': Like 'i', but allows one to include dictionary completion info. 86;; `u': Like `i', but the word is lower-cased first.
107;; 'C-l': redraws screen 87;; `m': Place entered value in personal dictionary, then recheck current word.
108;; 'C-r': recursive edit 88;; `C-l': redraws screen
109;; 'C-z': suspend emacs or iconify frame 89;; `C-r': recursive edit
110;; 90;; `C-z': suspend emacs or iconify frame
91
111;; Buffer-Local features: 92;; Buffer-Local features:
112;; There are a number of buffer-local features that can be used to customize 93;; There are a number of buffer-local features that can be used to customize
113;; ispell for the current buffer. This includes language dictionaries, 94;; ispell for the current buffer. This includes language dictionaries,
@@ -116,214 +97,61 @@
116;; including the keyword and argument(s) at the end of the buffer (usually 97;; including the keyword and argument(s) at the end of the buffer (usually
117;; prefixed by the comment characters). See the end of this file for 98;; prefixed by the comment characters). See the end of this file for
118;; examples. The local keywords and variables are: 99;; examples. The local keywords and variables are:
119;; 100
120;; ispell-dictionary-keyword language-dictionary 101;; ispell-dictionary-keyword language-dictionary
121;; uses local variable ispell-local-dictionary 102;; uses local variable ispell-local-dictionary
122;; ispell-pdict-keyword personal-dictionary 103;; ispell-pdict-keyword personal-dictionary
123;; uses local variable ispell-local-pdict 104;; uses local variable ispell-local-pdict
124;; ispell-parsing-keyword mode-arg extended-char-arg 105;; ispell-parsing-keyword mode-arg extended-char-arg
125;; ispell-words-keyword any number of local word spellings 106;; ispell-words-keyword any number of local word spellings
126;; 107
127;; 108;; Region skipping:
109;; Place new regular expression definitions of regions you prefer not to
110;; spell check in `ispell-skip-region-alist'. Mode-dependent features can
111;; be added to latex by modifying `ispell-tex-skip-alists'.
112;; `ispell-message' contains some custom skipping code for e-mail messages.
113
128;; BUGS: 114;; BUGS:
129;; Highlighting in version 19 still doesn't work on tty's. 115;; Highlighting in version 19 still doesn't work on tty's.
130;; On some versions of emacs, growing the minibuffer fails. 116;; On some versions of emacs, growing the minibuffer fails.
131;; 117;; Autoloading ispell can result in problems if you need to use a local or
132;; HISTORY 118;; modified dictionary. Place the following in your .emacs file to
133;; 119;; override the autoload definitions:
134;; Revision 2.38 1996/5/30 ethanb@phys.washington.edu 120;; (setq ispell-dictionary-alist (cons '(dictionary ...)
135;; Update ispell-message for gnus 5 (news-inews-hook => message-send-hook; 121;; ispell-dictionary-alist))
136;; different header for quoted message). 122;; (setq ispell-menu-map nil)
137;; 123;; (load-library "ispell")
138;; Revision 2.37 1995/6/13 12:05:28 stevens
139;; Removed autoload from ispell-dictionary-alist. *choices* mode-line shows
140;; misspelled word. Block skip for pgp & forwarded messages added.
141;; RMS: the autoload changes had problems and I removed them.
142;;
143;; Revision 2.36 1995/2/6 17:39:38 stevens
144;; Properly adjust screen with different ispell-choices-win-default-height
145;; settings. Skips SGML entity references.
146;;
147;; Revision 2.35 1995/1/13 14:16:46 stevens
148;; Skips SGML tags, ispell-change-dictionary fix for add-hook, assure personal
149;; dictionary is saved when called from the menu
150;;
151;; Revision 2.34 1994/12/08 13:17:41 stevens
152;; Interaction corrected to function with all 3.1 ispell versions.
153;;
154;; Revision 2.33 1994/11/24 02:31:20 stevens
155;; Repaired bug introduced in 2.32 that corrupts buffers when correcting.
156;; Improved buffer scrolling. Nondestructive buffer selections allowed.
157;;
158;; Revision 2.32 1994/10/31 21:10:08 geoff
159;; Many revisions accepted from RMS/FSF. I think (though I don't know) that
160;; this represents an 'official' version.
161;;
162;; Revision 2.31 1994/5/31 10:18:17 stevens
163;; Repaired comments. buffer-local commands executed in `ispell-word' now.
164;; German dictionary described for extended character mode. Dict messages.
165;;
166;; Revision 2.30 1994/5/20 22:18:36 stevens
167;; Continue ispell from ispell-word, C-z functionality fixed.
168;;
169;; Revision 2.29 1994/5/12 09:44:33 stevens
170;; Restored ispell-use-ptys-p, ispell-message aborts sends with interrupt.
171;; defined fn ispell
172;;
173;; Revision 2.28 1994/4/28 16:24:40 stevens
174;; Window checking when ispell-message put on gnus-inews-article-hook jwz.
175;; prefixed ispell- to highlight functions and horiz-scroll fn.
176;; Try and respect case of word in ispell-complete-word.
177;; Ignore non-char events. Ispell-use-ptys-p commented out. Lucid menu.
178;; Better interrupt handling. ispell-message improvements from Ethan.
179;;
180;; Revision 2.27
181;; version 18 explicit C-g handling disabled as it didn't work. Added
182;; ispell-extra-args for ispell customization (jwz)
183;;
184;; Revision 2.26 1994/2/15 16:11:14 stevens
185;; name changes for copyright assignment. Added word-frags in complete-word.
186;; Horizontal scroll (John Conover). Query-replace matches words now. bugs.
187;;
188;; Revision 2.25
189;; minor mods, upgraded ispell-message
190;;
191;; Revision 2.24
192;; query-replace more robust, messages, defaults, ispell-change-dict.
193;;
194;; Revision 2.23 1993/11/22 23:47:03 stevens
195;; ispell-message, Fixed highlighting, added menu-bar, fixed ispell-help, ...
196;;
197;; Revision 2.22
198;; Added 'u' command. Fixed default in ispell-local-dictionary.
199;; fixed affix rules display. Tib skipping more robust. Contributions by
200;; Per Abraham (parser selection), Denis Howe, and Eberhard Mattes.
201;;
202;; Revision 2.21 1993/06/30 14:09:04 stevens
203;; minor bugs. (nroff word skipping fixed)
204;;
205;; Revision 2.20 1993/06/30 14:09:04 stevens
206;;
207;; Debugging and contributions by: Boris Aronov, Rik Faith, Chris Moore,
208;; Kevin Rodgers, Malcolm Davis.
209;; Particular thanks to Michael Lipp, Jamie Zawinski, Phil Queinnec
210;; and John Heidemann for suggestions and code.
211;; Major update including many tweaks.
212;; Many changes were integrations of suggestions.
213;; lookup-words rehacked to use call-process (Jamie).
214;; ispell-complete-word rehacked to be compatible with the rest of the
215;; system for word searching and to include multiple wildcards,
216;; and its own dictionary.
217;; query-replace capability added. New options 'X', 'R', and 'A'.
218;; buffer-local modes for dictionary, word-spelling, and formatter-parsing.
219;; Many random bugs, like commented comments being skipped, fix to
220;; keep-choices-win, fix for math mode, added pipe mode choice,
221;; fixed 'q' command, ispell-word checks previous word and leave cursor
222;; in same location. Fixed tib code which could drop spelling regions.
223;; Cleaned up setq calls for efficiency. Gave more context on window overlays.
224;; Assure context on ispell-command-loop. Window lossage in look cmd fixed.
225;; Due to pervasive opinion, common-lisp package syntax removed. Display
226;; problem when not highlighting.
227;;
228;; Revision 2.19 1992/01/10 10:54:08 geoff
229;; Make another attempt at fixing the "Bogus, dude" problem. This one is
230;; less elegant, but has the advantage of working.
231;;
232;; Revision 2.18 1992/01/07 10:04:52 geoff
233;; Fix the "Bogus, Dude" problem in ispell-word.
234;;
235;; Revision 2.17 1991/09/12 00:01:42 geoff
236;; Add some changes to make ispell-complete-word work better, though
237;; still not perfectly.
238;;
239;; Revision 2.16 91/09/04 18:00:52 geoff
240;; More updates from Sebastian, to make the multiple-dictionary support
241;; more flexible.
242;;
243;; Revision 2.15 91/09/04 17:30:02 geoff
244;; Sebastian Kremer's tib support
245;;
246;; Revision 2.14 91/09/04 16:19:37 geoff
247;; Don't do set-window-start if the move-to-window-line moved us
248;; downward, rather than upward. This prevents getting the buffer all
249;; confused. Also, don't use the "not-modified" function to clear the
250;; modification flag; instead use set-buffer-modified-p. This prevents
251;; extra messages from flashing.
252;;
253;; Revision 2.13 91/09/04 14:35:41 geoff
254;; Fix a spelling error in a comment. Add code to handshake with the
255;; ispell process before sending anything to it.
256;;
257;; Revision 2.12 91/09/03 20:14:21 geoff
258;; Add Sebastian Kremer's multiple-language support.
259;;
260;;
261;; Walt Buehring
262;; Texas Instruments - Computer Science Center
263;; ARPA: Buehring%TI-CSL@CSNet-Relay
264;; UUCP: {smu, texsun, im4u, rice} ! ti-csl ! buehring
265;;
266;; ispell-region and associated routines added by
267;; Perry Smith
268;; pedz@bobkat
269;; Tue Jan 13 20:18:02 CST 1987
270;;
271;; extensively modified by Mark Davies and Andrew Vignaux
272;; {mark,andrew}@vuwcomp
273;; Sun May 10 11:45:04 NZST 1987
274;;
275;; Ken Stevens ARPA: k.stevens@ieee.org
276;; Tue Jan 3 16:59:07 PST 1989
277;; This file has overgone a major overhaul to be compatible with ispell
278;; version 2.1. Most of the functions have been totally rewritten, and
279;; many user-accessible variables have been added. The syntax table has
280;; been removed since it didn't work properly anyway, and a filter is
281;; used rather than a buffer. Regular expressions are used based on
282;; ispell's internal definition of characters (see ispell(4)).
283;; Some new updates:
284;; - Updated to version 3.0 to include terse processing.
285;; - Added a variable for the look command.
286;; - Fixed a bug in ispell-word when cursor is far away from the word
287;; that is to be checked.
288;; - Ispell places the incorrect word or guess in the minibuffer now.
289;; - fixed a bug with 'l' option when multiple windows are on the screen.
290;; - lookup-words just didn't work with the process filter. Fixed.
291;; - Rewrote the process filter to make it cleaner and more robust
292;; in the event of a continued line not being completed.
293;; - Made ispell-init-process more robust in handling errors.
294;; - Fixed bug in continuation location after a region has been modified by
295;; correcting a misspelling.
296;; Mon 17 Sept 1990
297;;
298;; Sebastian Kremer <sk@thp.uni-koeln.de>
299;; Wed Aug 7 14:02:17 MET DST 1991
300;; - Ported ispell-complete-word from Ispell 2 to Ispell 3.
301;; - Added ispell-kill-ispell command.
302;; - Added ispell-dictionary and ispell-dictionary-alist variables to
303;; support other than default language. See their docstrings and
304;; command ispell-change-dictionary.
305;; - (ispelled it :-)
306;; - Added ispell-skip-tib variable to support the tib bibliography
307;; program.
308
309
310;; **********************************************************************
311;; The following variables should be set according to personal preference
312;; and location of binaries:
313;; **********************************************************************
314
315;; ******* THIS FILE IS WRITTEN FOR ISPELL VERSION 3.1
316 124
317;;; Code: 125;;; Code:
318 126
319(defgroup ispell nil 127;;; Custom.el macros require recompiling this when they are not present.
320 "Spell checking using ispell" 128;;; Add in backward compatible custom support.
321 :group 'processes) 129(eval-when-compile
130 (if (not (fboundp 'defcustom))
131 (defmacro defcustom (symbol value doc &rest args)
132 "Empty replacement for defcustom when not supplied."
133 `(defvar ,symbol ,value ,doc))))
322 134
135(eval-when-compile
136 (if (fboundp 'defgroup)
137 (defgroup ispell nil
138 "User variables for emacs ispell interface."
139 :group 'applications)))
323 140
324(defcustom ispell-highlight-p t 141
325 "*Highlight spelling errors when non-nil." 142;;; **********************************************************************
326 :type 'boolean 143;;; The following variables should be set according to personal preference
144;;; and location of binaries:
145;;; **********************************************************************
146
147
148;;; ******* THIS FILE IS WRITTEN FOR ISPELL VERSION 3.1
149;;; Code:
150
151(defcustom ispell-highlight-p 'block
152 "*Highlight spelling errors when non-nil.
153When set to `block', assumes a block cursor with TTY displays."
154 :type '(choice (const block) (const t) (const nil))
327 :group 'ispell) 155 :group 'ispell)
328 156
329(defcustom ispell-highlight-face 'highlight 157(defcustom ispell-highlight-face 'highlight
@@ -337,8 +165,11 @@ slightly different."
337 :group 'ispell) 165 :group 'ispell)
338 166
339(defcustom ispell-check-comments t 167(defcustom ispell-check-comments t
340 "*If nil, don't check spelling of comments." 168 "*Spelling of comments checked when non-nil.
341 :type 'boolean 169When set to `exclusive', ONLY comments are checked. (For code comments).
170Warning! Not checking comments, when a comment start is embedded in strings,
171may produce undesired results."
172 :type '(choice (const exclusive) (const t) (const nil))
342 :group 'ispell) 173 :group 'ispell)
343 174
344(defcustom ispell-query-replace-choices nil 175(defcustom ispell-query-replace-choices nil
@@ -398,17 +229,39 @@ Must be greater than 1."
398 :type 'file 229 :type 'file
399 :group 'ispell) 230 :group 'ispell)
400 231
401(defvar ispell-grep-command "egrep" 232(defcustom ispell-message-dictionary-alist nil
402 "Name of the grep command for search processes.") 233 "*List used by `ispell-message' to select a new dictionary.
234It consists of pairs (REGEXP . DICTIONARY). If REGEXP is found
235in the message headers, `ispell-local-dictionary' will be set to
236DICTIONARY if `ispell-local-dictionary' is not buffer-local.
237E.g. you may use the following value:
238 '((\"^Newsgroups:[ \\t]*de\\\\.\" . \"deutsch8\")
239 (\"^To:[^\\n,]+\\\\.de[ \\t\\n,>]\" . \"deutsch8\"))"
240 :type '(repeat (cons regexp string))
241 :group 'ispell)
403 242
404(defvar ispell-grep-options "-i" 243
244(defcustom ispell-grep-command "egrep"
245 "Name of the grep command for search processes."
246 :type 'string
247 :group 'ispell)
248
249(defcustom ispell-grep-options "-i"
405 "String of options to use when running the program in `ispell-grep-command'. 250 "String of options to use when running the program in `ispell-grep-command'.
406Should probably be \"-i\" or \"-e\". 251Should probably be \"-i\" or \"-e\".
407Some machines (like the NeXT) don't support \"-i\"") 252Some machines (like the NeXT) don't support \"-i\""
253 :type 'string
254 :group 'ispell)
408 255
409(defvar ispell-look-command "look" 256(defcustom ispell-look-command
257 (cond ((file-exists-p "/bin/look") "/bin/look")
258 ((file-exists-p "/usr/local/bin/look") "/usr/local/bin/look")
259 ((file-exists-p "/usr/bin/look") "/usr/bin/look")
260 (t "look"))
410 "Name of the look command for search processes. 261 "Name of the look command for search processes.
411This must be an absolute file name.") 262This must be an absolute file name."
263 :type 'file
264 :group 'ispell)
412 265
413(defcustom ispell-look-p (file-exists-p ispell-look-command) 266(defcustom ispell-look-p (file-exists-p ispell-look-command)
414 "*Non-nil means use `look' rather than `grep'. 267 "*Non-nil means use `look' rather than `grep'.
@@ -421,12 +274,16 @@ Default is based on whether `look' seems to be available."
421 :type 'boolean 274 :type 'boolean
422 :group 'ispell) 275 :group 'ispell)
423 276
424(defvar ispell-look-options (if ispell-have-new-look "-dfr" "-df") 277(defcustom ispell-look-options (if ispell-have-new-look "-dfr" "-df")
425 "String of command options for `ispell-look-command'.") 278 "String of command options for `ispell-look-command'."
279 :type 'string
280 :group 'ispell)
426 281
427(defvar ispell-use-ptys-p nil 282(defcustom ispell-use-ptys-p nil
428 "When non-nil, Emacs uses ptys to communicate with Ispell. 283 "When non-nil, Emacs uses ptys to communicate with Ispell.
429When nil, Emacs uses pipes.") 284When nil, Emacs uses pipes."
285 :type 'boolean
286 :group 'ispell)
430 287
431(defcustom ispell-following-word nil 288(defcustom ispell-following-word nil
432 "*Non-nil means `ispell-word' checks the word around or after point. 289 "*Non-nil means `ispell-word' checks the word around or after point.
@@ -436,8 +293,15 @@ Otherwise `ispell-word' checks the preceding word."
436 293
437(defcustom ispell-help-in-bufferp nil 294(defcustom ispell-help-in-bufferp nil
438 "*Non-nil means display interactive keymap help in a buffer. 295 "*Non-nil means display interactive keymap help in a buffer.
439Otherwise use the minibuffer." 296The following valued are supported:
440 :type 'boolean 297 nil Expand the minibuffer and display a short help message
298 there for a couple of seconds.
299 t Pop up a new buffer and display a short help message there
300 for a couple of seconds.
301 electric Pop up a new buffer and display a long help message there.
302 User can browse and then exit the help mode."
303 :type '(choice (const electric) (const t) (const nil))
304
441 :group 'ispell) 305 :group 'ispell)
442 306
443(defcustom ispell-quietly nil 307(defcustom ispell-quietly nil
@@ -451,6 +315,14 @@ The function must take one string argument and return a string."
451 :type 'function 315 :type 'function
452 :group 'ispell) 316 :group 'ispell)
453 317
318(defcustom ispell-use-framepop-p nil
319 "When non-nil ispell uses framepop to display choices in a dedicated frame.
320You can set this variable to dynamically use framepop if you are in a
321window system by evaluating the following on startup to set this variable:
322 (and window-system (condition-case () (require 'framepop) (error nil)))"
323 :type 'boolean
324 :group 'ispell)
325
454;;;###autoload 326;;;###autoload
455(defcustom ispell-personal-dictionary nil 327(defcustom ispell-personal-dictionary nil
456 "*File name of your personal spelling dictionary, or nil. 328 "*File name of your personal spelling dictionary, or nil.
@@ -465,21 +337,33 @@ where DICTNAME is the name of your default dictionary."
465 :type 'boolean 337 :type 'boolean
466 :group 'ispell) 338 :group 'ispell)
467 339
468;;; This variable contains the current dictionary being used if the ispell 340;;; This is the local dictionary to use. When nil the default dictionary will
469;;; process is running. Otherwise it contains the global default. 341;;; be used. Change set-default call to use a new default dictionary.
470(defvar ispell-dictionary nil 342(defcustom ispell-local-dictionary nil
471 "If non-nil, a dictionary to use instead of the default one. 343 "If non-nil, the dictionary to be used for Ispell commands.
472This is passed to the ispell process using the `-d' switch and is 344The value must be a string dictionary name in `ispell-dictionary-alist'.
473used as key in `ispell-dictionary-alist' (which see). 345This variable becomes buffer-local when set in any fashion.
346
347Setting ispell-local-dictionary to a value has the same effect as
348calling \\[ispell-change-dictionary] with that value. This variable
349is automatically set when defined in the file with either
350`ispell-dictionary-keyword' or the Local Variable syntax.
351
352To create a non-standard default dictionary (not from ispell-dictionary-alist)
353call function set-default with the new dictionary name."
354 :type '(choice string
355 (const :tag "default" nil))
356 :group 'ispell)
357
358(make-variable-buffer-local 'ispell-local-dictionary)
359
360;; Call this function set up the default dictionary if not English.
361;;(set-default 'ispell-local-dictionary nil)
474 362
475You should set this variable before your first use of Emacs spell-checking
476commands in the Emacs session, or else use the \\[ispell-change-dictionary]
477command to change it. Otherwise, this variable only takes effect in a newly
478started Ispell process.")
479 363
480(defcustom ispell-extra-args nil 364(defcustom ispell-extra-args nil
481 "*If non-nil, a list of extra switches to pass to the Ispell program. 365 "*If non-nil, a list of extra switches to pass to the Ispell program.
482For example, '(\"-W\" \"3\") to cause it to accept all 1-3 character 366For example, (\"-W\" \"3\") to cause it to accept all 1-3 character
483words as correct. See also `ispell-dictionary-alist', which may be used 367words as correct. See also `ispell-dictionary-alist', which may be used
484for language-specific arguments." 368for language-specific arguments."
485 :type '(repeat string) 369 :type '(repeat string)
@@ -489,84 +373,115 @@ for language-specific arguments."
489;;; because otherwise this file gets autoloaded every time Emacs starts 373;;; because otherwise this file gets autoloaded every time Emacs starts
490;;; so that it can set up the menus and determine keyboard equivalents. 374;;; so that it can set up the menus and determine keyboard equivalents.
491 375
376;;; split dictionary so line length is smaller in loaddefs.el
377
492;;;###autoload 378;;;###autoload
493(defvar ispell-dictionary-alist-1 ; sk 9-Aug-1991 18:28 379(defvar ispell-dictionary-alist-1
494 '((nil ; default (english.aff) 380 '((nil ; default (English.aff)
495 "[A-Za-z]" "[^A-Za-z]" "[']" nil ("-B") nil) 381 "[A-Za-z]" "[^A-Za-z]" "[']" nil ("-B") nil nil)
496 ("english" ; make English explicitly selectable 382 ("american" ; make English explicitly selectable
497 "[A-Za-z]" "[^A-Za-z]" "[']" nil ("-B") nil) 383 "[A-Za-z]" "[^A-Za-z]" "[']" nil ("-B") nil nil)
498 ("british" ; British version 384 ("british" ; British version
499 "[A-Za-z]" "[^A-Za-z]" "[']" nil ("-B" "-d" "british") nil) 385 "[A-Za-z]" "[^A-Za-z]" "[']" nil ("-B" "-d" "british") nil nil)
500 ("american" ; American version 386 ("castellano" ; Spanish mode
501 "[A-Za-z]" "[^A-Za-z]" "[']" nil ("-B" "-d" "american") nil) 387 "[A-Z\301\311\315\323\332\334\321a-z\341\351\355\363\372\374\361]"
502 ("deutsch" ; deutsch.aff 388 "[^A-Z\301\311\315\323\332\334\321a-z\341\351\355\363\372\374\361]"
503 "[a-zA-Z\"]" "[^a-zA-Z\"]" "[']" t ("-C") "~tex") 389 "[---]" nil ("-B" "-d" "castellano") "~tex" iso-latin-1)
390 ("castellano8" ; 8 bit Spanish mode
391 "[A-Z\301\311\315\323\332\334\321a-z\341\351\355\363\372\374\361]"
392 "[^A-Z\301\311\315\323\332\334\321a-z\341\351\355\363\372\374\361]"
393 "[---]" nil ("-B" "-d" "castellano") "~latin1" iso-latin-1)
394 ("czech"
395 "[A-Za-z\301\311\314\315\323\332\331\335\256\251\310\330\317\253\322\341\351\354\355\363\372\371\375\276\271\350\370\357\273\362]"
396 "[^A-Za-z\301\311\314\315\323\332\331\335\256\251\310\330\317\253\322\341\351\354\355\363\372\371\375\276\271\350\370\357\273\362]"
397 "" nil ("-B" "-d" "czech") nil iso-latin-2)
398 ("dansk" ; Dansk.aff
399 "[A-Z\306\330\305a-z\346\370\345]" "[^A-Z\306\330\305a-z\346\370\345]"
400 "[']" nil ("-C") nil iso-latin-1)
401 ("deutsch" ; Deutsch.aff
402 "[a-zA-Z\"]" "[^a-zA-Z\"]" "[']" t ("-C") "~tex" nil)
504 ("deutsch8" 403 ("deutsch8"
505 "[a-zA-Z\304\326\334\344\366\337\374]" 404 "[a-zA-Z\304\326\334\344\366\337\374]"
506 "[^a-zA-Z\304\326\334\344\366\337\374]" 405 "[^a-zA-Z\304\326\334\344\366\337\374]"
507 "[']" t ("-C" "-d" "deutsch") "~latin1" iso-latin-1) 406 "[']" t ("-C" "-d" "deutsch") "~latin1" iso-latin-1)
508 ("nederlands" ; nederlands.aff 407 ("english" ; make English explicitly selectable
509 "[A-Za-z\300-\305\307\310-\317\322-\326\331-\334\340-\345\347\350-\357\361\362-\366\371-\374]" 408 "[A-Za-z]" "[^A-Za-z]" "[']" nil ("-B") nil nil))
510 "[^A-Za-z\300-\305\307\310-\317\322-\326\331-\334\340-\345\347\350-\357\361\362-\366\371-\374]" 409 "First half of dictionary, shorteded for loaddefs.el")
511 "[']" t ("-C") nil iso-latin-1)
512 ("nederlands8" ; dutch8.aff
513 "[A-Za-z\300-\305\307\310-\317\322-\326\331-\334\340-\345\347\350-\357\361\362-\366\371-\374]"
514 "[^A-Za-z\300-\305\307\310-\317\322-\326\331-\334\340-\345\347\350-\357\361\362-\366\371-\374]"
515 "[']" t ("-C") nil iso-latin-1)))
516 410
517;;;###autoload 411;;;###autoload
518(defvar ispell-dictionary-alist-2 412(defvar ispell-dictionary-alist-2
519 '(("svenska" ;7 bit swedish mode 413 '(("esperanto"
520 "[A-Za-z}{|\\133\\135\\\\]" "[^A-Za-z}{|\\133\\135\\\\]" 414 "[A-Za-z\246\254\266\274\306\330\335\336\346\370\375\376]"
521 "[']" nil ("-C") nil) 415 "[^A-Za-z\246\254\266\274\306\330\335\336\346\370\375\376]"
522 ("svenska8" ;8 bit swedish mode 416 "[-']" t ("-C") "~latin3" nil)
523 "[A-Za-z\345\344\366\305\304\366]" "[^A-Za-z\345\344\366\305\304\366]" 417 ("esperanto-tex"
524 "[']" nil ("-C" "-d" "svenska") "~list" ; Add `"-T" "list"' instead? 418 "[A-Za-z^\\]" "[^A-Za-z^\\]" "[-'`\"]" t ("-C" "-d" "esperanto") "~tex"
525 iso-latin-1) 419 nil)
526 ("francais7" 420 ("francais7"
527 "[A-Za-z]" "[^A-Za-z]" "[`'^---]" t nil nil) 421 "[A-Za-z]" "[^A-Za-z]" "[`'^---]" t nil nil nil)
528 ("francais" ; francais.aff 422 ("francais" ; Francais.aff
529 "[A-Za-z\300\302\306\307\310\311\312\313\316\317\324\331\333\334\340\342\347\350\351\352\353\356\357\364\371\373\374]" 423 "[A-Za-z\300\302\306\307\310\311\312\313\316\317\324\331\333\334\340\342\347\350\351\352\353\356\357\364\371\373\374]"
530 "[^A-Za-z\300\302\306\307\310\311\312\313\316\317\324\331\333\334\340\342\347\350\351\352\353\356\357\364\371\373\374]" 424 "[^A-Za-z\300\302\306\307\310\311\312\313\316\317\324\331\333\334\340\342\347\350\351\352\353\356\357\364\371\373\374]"
531 "[---']" t nil "~list" iso-latin-1) 425 "[---']" t nil "~list" iso-latin-1)
532 ("francais-tex" ; francais.aff 426 ("francais-tex" ; Francais.aff
533 "[A-Za-z\300\302\306\307\310\311\312\313\316\317\324\331\333\334\340\342\347\350\351\352\353\356\357\364\371\373\374\\]" 427 "[A-Za-z\300\302\306\307\310\311\312\313\316\317\324\331\333\334\340\342\347\350\351\352\353\356\357\364\371\373\374\\]"
534 "[^A-Za-z\300\302\306\307\310\311\312\313\316\317\324\331\333\334\340\342\347\350\351\352\353\356\357\364\371\373\374\\]" 428 "[^A-Za-z\300\302\306\307\310\311\312\313\316\317\324\331\333\334\340\342\347\350\351\352\353\356\357\364\371\373\374\\]"
535 "[---'^`\"]" t nil "~tex" iso-latin-1) 429 "[---'^`\"]" t nil "~tex" iso-latin-1)
536 ("dansk" ; dansk.aff 430 ("nederlands" ; Nederlands.aff
537 "[A-Z\306\330\305a-z\346\370\345]" "[^A-Z\306\330\305a-z\346\370\345]" 431 "[A-Za-z\300-\305\307\310-\317\322-\326\331-\334\340-\345\347\350-\357\361\362-\366\371-\374]"
538 "[']" nil ("-C") nil iso-latin-1) 432 "[^A-Za-z\300-\305\307\310-\317\322-\326\331-\334\340-\345\347\350-\357\361\362-\366\371-\374]"
539 )) 433 "[']" t ("-C") nil iso-latin-1)
434 ("nederlands8" ; Dutch8.aff
435 "[A-Za-z\300-\305\307\310-\317\322-\326\331-\334\340-\345\347\350-\357\361\362-\366\371-\374]"
436 "[^A-Za-z\300-\305\307\310-\317\322-\326\331-\334\340-\345\347\350-\357\361\362-\366\371-\374]"
437 "[']" t ("-C") nil iso-latin-1)
438 ("norsk" ;8 bit Norwegian mode
439 "[A-Za-z\351\346\370\345\350\364\362\311\306\330\305\310\324\322]"
440 "[^A-Za-z\351\346\370\345\350\364\362\311\306\330\305\310\324\322]"
441 "[']" nil ("-C" "-d" "norsk") "~list" nil)
442 ("russian" ; russian.aff (KOI8-R charset)
443 "[\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]"
444 "[^\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]"
445 "[']" t ("-C" "-d" "russian") "~latin1" iso-latin-1)
446 ("svenska" ;7 bit Swedish mode
447 "[A-Za-z}{|\\133\\135\\\\]" "[^A-Za-z}{|\\133\\135\\\\]"
448 "[']" nil ("-C") nil nil)
449 ("svenska8" ;8 bit Swedish mode
450 "[A-Za-z\345\344\366\305\304\366]" "[^A-Za-z\345\344\366\305\304\366]"
451 "[']" nil ("-C" "-d" "svenska") "~list" ; Add `"-T" "list"' instead?
452 iso-latin-1))
453 "Second half of dictionary, shorteded for loaddefs.el")
540 454
455;;; The preparation of the menu bar menu must be autoloaded
456;;; because otherwise this file gets autoloaded every time Emacs starts
457;;; so that it can set up the menus and determine keyboard equivalents.
541 458
542;;; ispell-dictionary-alist is set up from two subvariables above
543;;; to avoid having very long lines in loaddefs.el.
544;;;###autoload 459;;;###autoload
545(defvar ispell-dictionary-alist 460(defcustom ispell-dictionary-alist
546 (append ispell-dictionary-alist-1 ispell-dictionary-alist-2) 461 (append ispell-dictionary-alist-1 ispell-dictionary-alist-2)
547 "An alist of dictionaries and their associated parameters. 462 "An alist of dictionaries and their associated parameters.
548 463
549Each element of this list is also a list: 464Each element of this list is also a list:
550 465
551\(DICTIONARY-NAME CASECHARS NOT-CASECHARS OTHERCHARS MANY-OTHERCHARS-P 466\(DICTIONARY-NAME CASECHARS NOT-CASECHARS OTHERCHARS MANY-OTHERCHARS-P
552 ISPELL-ARGS EXTENDED-CHARACTER-MODE\) 467 ISPELL-ARGS EXTENDED-CHARACTER-MODE CHARACTER-SET\)
553 468
554DICTIONARY-NAME is a possible value of variable `ispell-dictionary', nil 469DICTIONARY-NAME is a possible string value of variable `ispell-dictionary',
555means the default dictionary. 470nil means the default dictionary.
556 471
557CASECHARS is a regular expression of valid characters that comprise a 472CASECHARS is a regular expression of valid characters that comprise a
558word. 473word.
559 474
560NOT-CASECHARS is the opposite regexp of CASECHARS. 475NOT-CASECHARS is the opposite regexp of CASECHARS.
561 476
562OTHERCHARS are characters in the NOT-CASECHARS set but which can be used to 477OTHERCHARS is a regexp of characters in the NOT-CASECHARS set but which can be
563construct words in some special way. If OTHERCHARS characters follow and 478used to construct words in some special way. If OTHERCHARS characters follow
564precede characters from CASECHARS, they are parsed as part of a word, 479and precede characters from CASECHARS, they are parsed as part of a word,
565otherwise they become word-breaks. As an example in English, assume the 480otherwise they become word-breaks. As an example in English, assume the
566set ['] (as a regular expression) for OTHERCHARS. Then \"they're\" and 481regular expression \"[']\" for OTHERCHARS. Then \"they're\" and
567\"Steven's\" are parsed as single words including the \"'\" character, but 482\"Steven's\" are parsed as single words including the \"'\" character, but
568\"Stevens'\" does not include the quote character as part of the word. 483\"Stevens'\" does not include the quote character as part of the word.
569If you want OTHERCHARS to be empty, use nil. 484If you want OTHERCHARS to be empty, use the empty string.
570Hint: regexp syntax requires the hyphen to be declared first here. 485Hint: regexp syntax requires the hyphen to be declared first here.
571 486
572MANY-OTHERCHARS-P is non-nil when multiple OTHERCHARS are allowed in a word. 487MANY-OTHERCHARS-P is non-nil when multiple OTHERCHARS are allowed in a word.
@@ -585,29 +500,51 @@ but the dictionary can control the extended character mode.
585Both defaults can be overruled in a buffer-local fashion. See 500Both defaults can be overruled in a buffer-local fashion. See
586`ispell-parsing-keyword' for details on this. 501`ispell-parsing-keyword' for details on this.
587 502
503CHARACTER-SET used for languages with multibyte characters.
504
588Note that the CASECHARS and OTHERCHARS slots of the alist should 505Note that the CASECHARS and OTHERCHARS slots of the alist should
589contain the same character set as casechars and otherchars in the 506contain the same character set as casechars and otherchars in the
590language.aff file \(e.g., english.aff\).") 507LANGUAGE.aff file \(e.g., english.aff\)."
508 :type '(repeat (list (choice :tag "Dictionary"
509 (string :tag "Dictionary name")
510 (const :tag "default" nil))
511 (regexp :tag "Case characters")
512 (regexp :tag "Non case characters")
513 (regexp :tag "Other characters")
514 (boolean :tag "Many other characters")
515 (repeat :tag "Ispell command line args"
516 (string :tag "Arg"))
517 (choice :tag "Extended character mode"
518 (const "~tex") (const "~list") (const "~nroff")
519 (const "~latin3") (const "~latin1")
520 (const :tag "default" nil))
521 (choice :tag "Character set"
522 (const iso-latin-1)
523 (const iso-latin-2)
524 (const :tag "default" nil))))
525 :group 'ispell)
526
591 527
592;;;###autoload 528;;;###autoload
593(defvar ispell-menu-map nil "Key map for ispell menu") 529(defvar ispell-menu-map nil "Key map for ispell menu")
594 530
595;;;###autoload 531;;;###autoload
596(defvar ispell-menu-lucid nil "Spelling menu for Lucid Emacs.") 532(defvar ispell-menu-xemacs nil
533 "Spelling menu for XEmacs.
534If nil when package is loaded, a standard menu will be set,
535and added as a submenu of the \"Edit\" menu.")
597 536
598;;; Break out lucid menu and split into several calls to avoid having 537;;; Break out XEmacs menu and split into several calls to avoid having
599;;; long lines in loaddefs.el. Detect need off following constant. 538;;; long lines in loaddefs.el. Detect need off following constant.
600 539
540;;; Set up dictionary
601;;;###autoload 541;;;###autoload
602(defconst ispell-menu-map-needed ; make sure this is not Lucid Emacs 542(defconst ispell-menu-map-needed
543 ;; only needed when not version 18 and not XEmacs.
603 (and (not ispell-menu-map) 544 (and (not ispell-menu-map)
604;;; This is commented out because it fails in Emacs. 545 (not (string-match "18\\.[0-9]+\\.[0-9]+" emacs-version))
605;;; due to the fact that menu-bar is loaded much later than loaddefs. 546 (not (string-match "Lucid\\|XEmacs" emacs-version))))
606;;; ;; make sure this isn't Lucid Emacs
607;;; (featurep 'menu-bar)
608 (not (string-match "Lucid" emacs-version))))
609 547
610;;; Set up dictionary
611;;;###autoload 548;;;###autoload
612(if ispell-menu-map-needed 549(if ispell-menu-map-needed
613 (let ((dicts (reverse (cons (cons "default" nil) ispell-dictionary-alist))) 550 (let ((dicts (reverse (cons (cons "default" nil) ispell-dictionary-alist)))
@@ -645,6 +582,8 @@ language.aff file \(e.g., english.aff\).")
645 '("Continue Check" . ispell-continue)) 582 '("Continue Check" . ispell-continue))
646 (define-key ispell-menu-map [ispell-word] 583 (define-key ispell-menu-map [ispell-word]
647 '("Check Word" . ispell-word)) 584 '("Check Word" . ispell-word))
585 (define-key ispell-menu-map [ispell-comments-and-strings]
586 '("Check Comments" . ispell-comments-and-strings))
648 (define-key ispell-menu-map [ispell-region] 587 (define-key ispell-menu-map [ispell-region]
649 '("Check Region" . ispell-region)) 588 '("Check Region" . ispell-region))
650 (define-key ispell-menu-map [ispell-buffer] 589 (define-key ispell-menu-map [ispell-buffer]
@@ -661,9 +600,12 @@ language.aff file \(e.g., english.aff\).")
661 (put 'ispell-region 'menu-enable 'mark-active) 600 (put 'ispell-region 'menu-enable 'mark-active)
662 (fset 'ispell-menu-map (symbol-value 'ispell-menu-map)))) 601 (fset 'ispell-menu-map (symbol-value 'ispell-menu-map))))
663 602
664;;; Xemacs version 19 603;;; XEmacs version 19 & 20
665(if (and (string-lessp "19" emacs-version) 604(if (and (not (string-match "18\\.[0-9]+\\.[0-9]+" emacs-version))
666 (string-match "Lucid" emacs-version)) 605 (string-match "Lucid\\|XEmacs" emacs-version)
606 (featurep 'menubar)
607 (null ispell-menu-xemacs)
608 (not (and (boundp 'infodock-version) infodock-version)))
667 (let ((dicts (cons (cons "default" nil) ispell-dictionary-alist)) 609 (let ((dicts (cons (cons "default" nil) ispell-dictionary-alist))
668 (current-menubar (or current-menubar default-menubar)) 610 (current-menubar (or current-menubar default-menubar))
669 (menu 611 (menu
@@ -671,6 +613,7 @@ language.aff file \(e.g., english.aff\).")
671 ;;["Help" (popup-menu ispell-help-list) t] 613 ;;["Help" (popup-menu ispell-help-list) t]
672 ["Check Message" ispell-message t] 614 ["Check Message" ispell-message t]
673 ["Check Buffer" ispell-buffer t] 615 ["Check Buffer" ispell-buffer t]
616 ["Check Comments" ispell-comments-and-strings t]
674 ["Check Word" ispell-word t] 617 ["Check Word" ispell-word t]
675 ["Check Region" ispell-region (or (not zmacs-regions) (mark))] 618 ["Check Region" ispell-region (or (not zmacs-regions) (mark))]
676 ["Continue Check" ispell-continue t] 619 ["Continue Check" ispell-continue t]
@@ -687,14 +630,21 @@ language.aff file \(e.g., english.aff\).")
687 (if (stringp name) 630 (if (stringp name)
688 (setq menu (append menu 631 (setq menu (append menu
689 (list 632 (list
690 (vector (concat "Select " (capitalize name)) 633 (vector (concat "Select " (capitalize name))
691 (list 'ispell-change-dictionary name) 634 (list 'ispell-change-dictionary name)
692 t)))))) 635 t))))))
693 (setq ispell-menu-lucid menu) 636 (setq ispell-menu-xemacs menu)
694 (if current-menubar 637 (if current-menubar
695 (progn 638 (progn
696 (delete-menu-item '("Edit" "Spell")) ; in case already defined 639 (delete-menu-item '("Edit" "Spell")) ; in case already defined
697 (add-menu '("Edit") "Spell" ispell-menu-lucid))))) 640 (add-menu '("Edit") "Spell" ispell-menu-xemacs)))))
641
642;;; Allow incrementing characters as integers in XEmacs 20
643(if (and (string-match "XEmacs" emacs-version)
644 (fboundp 'int-char))
645 (fset 'ispell-int-char 'int-char)
646 ;; Emacs and XEmacs 19 or earlier
647 (fset 'ispell-int-char 'identity))
698 648
699 649
700;;; ********************************************************************** 650;;; **********************************************************************
@@ -706,15 +656,27 @@ language.aff file \(e.g., english.aff\).")
706;;; There is an incompatibility between version 3.1.12 and lower versions. 656;;; There is an incompatibility between version 3.1.12 and lower versions.
707(defconst ispell-required-version '("3.1." 12) 657(defconst ispell-required-version '("3.1." 12)
708 "Ispell versions with which this version of ispell.el is known to work.") 658 "Ispell versions with which this version of ispell.el is known to work.")
709(defvar ispell-offset 1 659(defvar ispell-offset -1
710 "Offset that maps protocol differences between ispell 3.1 versions.") 660 "Offset that maps protocol differences between ispell 3.1 versions.")
711 661
662;;; This variable contains the current dictionary being used if the ispell
663;;; process is running. Otherwise it contains the global default.
664(defvar ispell-dictionary nil
665 "The name of the current dictionary, or nil for the default.
666When `ispell-local-dictionary' is nil, `ispell-dictionary' is used to select
667the dictionary for new buffers.
668
669This is passed to the ispell process using the `-d' switch and is
670used as key in `ispell-dictionary-alist' (which see).")
671
712(defun ispell-decode-string (str) 672(defun ispell-decode-string (str)
713 (let (coding-system) 673 "Decodes multibyte character strings."
714 (if (and enable-multibyte-characters 674 (if (and (boundp 'enable-multibyte-characters)
715 (setq coding-system (ispell-get-coding-system))) 675 (fboundp 'decode-coding-string)
716 (decode-coding-string str coding-system) 676 enable-multibyte-characters
717 str))) 677 (ispell-get-coding-system))
678 (decode-coding-string str (ispell-get-coding-system))
679 str))
718 680
719(defun ispell-get-casechars () 681(defun ispell-get-casechars ()
720 (ispell-decode-string 682 (ispell-decode-string
@@ -757,6 +719,9 @@ language.aff file \(e.g., english.aff\).")
757(defvar ispell-query-replace-marker (make-marker) 719(defvar ispell-query-replace-marker (make-marker)
758 "Marker for `query-replace' processing.") 720 "Marker for `query-replace' processing.")
759 721
722(defvar ispell-recursive-edit-marker (make-marker)
723 "Marker for return point from recursive edit.")
724
760(defvar ispell-checking-message nil 725(defvar ispell-checking-message nil
761 "Non-nil when we're checking a mail message") 726 "Non-nil when we're checking a mail message")
762 727
@@ -766,47 +731,95 @@ language.aff file \(e.g., english.aff\).")
766 731
767;;; *** Buffer Local Definitions *** 732;;; *** Buffer Local Definitions ***
768 733
769;;; This is the local dictionary to use. When nil the default dictionary will 734(defconst ispell-words-keyword "LocalWords: "
770;;; be used. Do not redefine default value or it will override the global!
771(defvar ispell-local-dictionary nil
772 "If non-nil, a dictionary to use for Ispell commands in this buffer.
773The value must be a string dictionary name in `ispell-dictionary-alist'.
774This variable becomes buffer-local when set in any fashion.
775
776Setting ispell-local-dictionary to a value has the same effect as
777calling \\[ispell-change-dictionary] with that value. This variable
778is automatically set when defined in the file with either
779`ispell-dictionary-keyword' or the Local Variable syntax.")
780
781(make-variable-buffer-local 'ispell-local-dictionary)
782
783;; Use default directory, unless locally set.
784(set-default 'ispell-local-dictionary nil)
785
786(defconst ispell-words-keyword "LocalWords: "
787 "The keyword for local oddly-spelled words to accept. 735 "The keyword for local oddly-spelled words to accept.
788The keyword will be followed by any number of local word spellings. 736The keyword will be followed by any number of local word spellings.
789There can be multiple of these keywords in the file.") 737There can be multiple of these keywords in the file.")
790 738
791(defconst ispell-dictionary-keyword "Local IspellDict: " 739(defconst ispell-dictionary-keyword "Local IspellDict: "
792 "The keyword for local dictionary definitions. 740 "The keyword for a local dictionary to use.
793There should be only one dictionary keyword definition per file, and it 741The keyword must be followed by a correct dictionary name in
794should be followed by a correct dictionary name in `ispell-dictionary-alist'.") 742`ispell-dictionary-alist'. When multiple occurrences exist, the last keyword
743definition is used.")
744
745(defconst ispell-pdict-keyword "Local IspellPersDict: "
746 "The keyword for defining buffer local dictionaries.
747Keyword must be followed by the filename of a personal dictionary.
748The last occurring definition in the buffer will be used.")
795 749
796(defconst ispell-parsing-keyword "Local IspellParsing: " 750(defconst ispell-parsing-keyword "Local IspellParsing: "
797 "The keyword for overriding default Ispell parsing. 751 "The keyword for overriding default Ispell parsing.
798Determined by the buffer's major mode and extended-character mode as well as
799the default dictionary.
800
801The above keyword string should be followed by `latex-mode' or 752The above keyword string should be followed by `latex-mode' or
802`nroff-mode' to put the current buffer into the desired parsing mode. 753`nroff-mode' to put the current buffer into the desired parsing mode.
803 754
804Extended character mode can be changed for this buffer by placing 755Extended character mode can be changed for this buffer by placing
805a `~' followed by an extended-character mode -- such as `~.tex'.") 756a `~' followed by an extended-character mode -- such as `~.tex'.
757The last occurring definition in the buffer will be used.")
758
759;;;###autoload
760(defvar ispell-skip-region-alist
761 '((ispell-words-keyword forward-line)
762 (ispell-dictionary-keyword forward-line)
763 (ispell-pdict-keyword forward-line)
764 (ispell-parsing-keyword forward-line)
765 ("^---*BEGIN PGP [A-Z ]*--*" . "^---*END PGP [A-Z ]*--*")
766 ("^---* \\(Start of \\)?[Ff]orwarded [Mm]essage" . "^---* End of [Ff]orwarded [Mm]essage")
767 ;; matches e-mail addresses, file names, http addresses, etc.
768 ("\\(/\\|\\(\\(\\w\\|-\\)+[.:@]\\)\\)\\(\\w\\|-\\)*\\([.:/@]+\\(\\w\\|-\\|~\\)+\\)+")
769 ;; This is a pretty complex regexp. It can be simplified to the following:
770 ;; "\\(\\w\\|-\\)*\\([.:/@]+\\(\\w\\|-\\|~\\)+\\)+"
771 ;; but some valid text will be skipped, e.g. "his/herr". This could be
772 ;; fixed up (at the expense of a moderately more complex regexp)
773 ;; by not allowing "/" to be the character which triggers the
774 ;; identification of the computer name, e.g.:
775 ;; "\\(\\w\\|-\\)+[.:@]\\(\\w\\|-\\)*\\([.:/@]+\\(\\w\\|-\\|~\\)+\\)+"
776 )
777 "A-list expressing begining and end of regions not to spell check.
778The alist key must be a regular expression.
779Valid forms include:
780 (KEY) - just skip the key.
781 (KEY . REGEXP) - skip to the end REGEXP. REGEXP may be string or symbol.
782 (KEY REGEXP) - skip to end of REGEXP. REGEXP must be a string.
783 (KEY FUNCTION ARGS) - function called with args returns end of region.")
784
806 785
807(defvar ispell-skip-sgml nil 786
808 "Skips spell checking of SGML tags and entity references when non-nil. 787;;;###autoload
809This variable is set when major-mode is sgml-mode or html-mode.") 788(defvar ispell-tex-skip-alists
789 '((("%\\[" . "%\\]")
790 ;; All the standard LaTeX keywords from L. Lamport's guide:
791 ;; \cite, \hspace, \hspace*, \hyphenation, \include, \includeonly, \input,
792 ;; \label, \nocite, \rule (in ispell - rest included here)
793 ("\\\\addcontentsline" ispell-tex-arg-end 2)
794 ("\\\\add\\(tocontents\\|vspace\\)" ispell-tex-arg-end)
795 ("\\\\\\([aA]lph\\|arabic\\)" ispell-tex-arg-end)
796 ("\\\\author" ispell-tex-arg-end)
797 ("\\\\bibliographystyle" ispell-tex-arg-end)
798 ("\\\\makebox" ispell-tex-arg-end 0)
799 ;;("\\\\epsfig" ispell-tex-arg-end)
800 ("\\\\document\\(class\\|style\\)" .
801 "\\\\begin[ \t\n]*{[ \t\n]*document[ \t\n]*}"))
802 (;; delimited with \begin. In ispell: displaymath, eqnarray, eqnarray*,
803 ;; equation, minipage, picture, tabular, tabular* (ispell)
804 ("\\(figure\\|table\\)\\*?" ispell-tex-arg-end 0)
805 ("list" ispell-tex-arg-end 2)
806 ("program" . "\\\\end[ \t\n]*{[ \t\n]*program[ \t\n]*}")
807 ("verbatim\\*?" . "\\\\end[ \t\n]*{[ \t\n]*verbatim\\*?[ \t\n]*}")))
808 "*Lists of regions to be skipped in TeX mode.
809First list is used raw.
810Second list has key placed inside \\begin{}.
811
812Delete or add any regions you want to be automatically selected
813for skipping in latex mode.")
814
815
816(defcustom ispell-skip-sgml 'use-mode-name
817 "*Indicates whether ispell should skip spell checking of SGML markup.
818If t, always skip SGML markup; if nil, never skip; if non-t and non-nil,
819guess whether SGML markup should be skipped according to the name of the
820buffer's major mode."
821 :type '(choice (const use-mode-name) (const t) (const nil))
822 :group 'ispell)
810 823
811(defvar ispell-local-pdict ispell-personal-dictionary 824(defvar ispell-local-pdict ispell-personal-dictionary
812 "A buffer local variable containing the current personal dictionary. 825 "A buffer local variable containing the current personal dictionary.
@@ -820,9 +833,6 @@ local variable syntax.")
820 833
821(make-variable-buffer-local 'ispell-local-pdict) 834(make-variable-buffer-local 'ispell-local-pdict)
822 835
823(defconst ispell-pdict-keyword "Local IspellPersDict: "
824 "The keyword for defining buffer local dictionaries.")
825
826(defvar ispell-buffer-local-name nil 836(defvar ispell-buffer-local-name nil
827 "Contains the buffer name if local word definitions were used. 837 "Contains the buffer name if local word definitions were used.
828Ispell is then restarted because the local words could conflict.") 838Ispell is then restarted because the local words could conflict.")
@@ -830,8 +840,8 @@ Ispell is then restarted because the local words could conflict.")
830(defvar ispell-parser 'use-mode-name 840(defvar ispell-parser 'use-mode-name
831 "*Indicates whether ispell should parse the current buffer as TeX Code. 841 "*Indicates whether ispell should parse the current buffer as TeX Code.
832Special value `use-mode-name' tries to guess using the name of major-mode. 842Special value `use-mode-name' tries to guess using the name of major-mode.
833Default parser is 'nroff. 843Default parser is `nroff'.
834Currently the only other valid parser is 'tex. 844Currently the only other valid parser is `tex'.
835 845
836You can set this variable in hooks in your init file -- eg: 846You can set this variable in hooks in your init file -- eg:
837 847
@@ -848,10 +858,15 @@ You can set this variable in hooks in your init file -- eg:
848;;; ********************************************************************** 858;;; **********************************************************************
849 859
850 860
851(and (string-lessp "19" emacs-version) 861
862(and (not (string-match "18\\.[0-9]+\\.[0-9]+" emacs-version))
852 (not (boundp 'epoch::version)) 863 (not (boundp 'epoch::version))
853 (defalias 'ispell 'ispell-buffer)) 864 (defalias 'ispell 'ispell-buffer))
854 865
866(if (not (fboundp 'buffer-substring-no-properties))
867 (defun buffer-substring-no-properties (start end)
868 (buffer-substring start end)))
869
855;;;###autoload 870;;;###autoload
856(define-key global-map "\M-$" 'ispell-word) 871(define-key global-map "\M-$" 'ispell-word)
857 872
@@ -882,17 +897,15 @@ or \\[ispell-region] to update the Ispell process."
882 quietly ispell-quietly)) 897 quietly ispell-quietly))
883 (ispell-accept-buffer-local-defs) ; use the correct dictionary 898 (ispell-accept-buffer-local-defs) ; use the correct dictionary
884 (let ((cursor-location (point)) ; retain cursor location 899 (let ((cursor-location (point)) ; retain cursor location
885 (opoint (point))
886 (word (ispell-get-word following)) 900 (word (ispell-get-word following))
887 start end poss replace) 901 start end poss new-word replace)
888 (unless (or (equal (car word) "") 902 ;; De-structure return word info list.
889 (< (nth 2 word) opoint)) 903 (setq start (car (cdr word))
890 ;; destructure return word info list. 904 end (car (cdr (cdr word)))
891 (setq start (car (cdr word)) 905 word (car word))
892 end (car (cdr (cdr word))) 906
893 word (car word)) 907 ;; now check spelling of word if it has 3 or more characters.
894 908 (when (> (length word) 2)
895 ;; now check spelling of word.
896 (or quietly 909 (or quietly
897 (message "Checking spelling of %s..." 910 (message "Checking spelling of %s..."
898 (funcall ispell-format-word word))) 911 (funcall ispell-format-word word)))
@@ -903,12 +916,13 @@ or \\[ispell-region] to update the Ispell process."
903 (accept-process-output ispell-process) 916 (accept-process-output ispell-process)
904 (not (string= "" (car ispell-filter))))) 917 (not (string= "" (car ispell-filter)))))
905 ;;(process-send-string ispell-process "!\n") ;back to terse mode. 918 ;;(process-send-string ispell-process "!\n") ;back to terse mode.
906 (setq ispell-filter (cdr ispell-filter)) 919 (setq ispell-filter (cdr ispell-filter)) ; remove extra \n
907 (if (listp ispell-filter) 920 (if (listp ispell-filter)
908 (setq poss (ispell-parse-output (car ispell-filter)))) 921 (setq poss (ispell-parse-output (car ispell-filter))))
909 (cond ((eq poss t) 922 (cond ((eq poss t)
910 (or quietly 923 (or quietly
911 (message "%s is correct" (funcall ispell-format-word word)))) 924 (message "%s is correct"
925 (funcall ispell-format-word word))))
912 ((stringp poss) 926 ((stringp poss)
913 (or quietly 927 (or quietly
914 (message "%s is correct because of root %s" 928 (message "%s is correct because of root %s"
@@ -916,8 +930,8 @@ or \\[ispell-region] to update the Ispell process."
916 (funcall ispell-format-word poss)))) 930 (funcall ispell-format-word poss))))
917 ((null poss) (message "Error in ispell process")) 931 ((null poss) (message "Error in ispell process"))
918 (ispell-check-only ; called from ispell minor mode. 932 (ispell-check-only ; called from ispell minor mode.
919 (message "Misspelled word `%s'" word) 933 (beep)
920 (beep)) 934 (message "%s is incorrect" (funcall ispell-format-word word)))
921 (t ; prompt for correct word. 935 (t ; prompt for correct word.
922 (save-window-excursion 936 (save-window-excursion
923 (setq replace (ispell-command-loop 937 (setq replace (ispell-command-loop
@@ -927,17 +941,21 @@ or \\[ispell-region] to update the Ispell process."
927 (cond ((equal 0 replace) 941 (cond ((equal 0 replace)
928 (ispell-add-per-file-word-list (car poss))) 942 (ispell-add-per-file-word-list (car poss)))
929 (replace 943 (replace
930 (setq word (if (atom replace) replace (car replace)) 944 (setq new-word (if (atom replace) replace (car replace))
931 cursor-location (+ (- (length word) (- end start)) 945 cursor-location (+ (- (length word) (- end start))
932 cursor-location)) 946 cursor-location))
933 (if (not (equal word (car poss))) 947 (if (not (equal new-word (car poss)))
934 (progn 948 (progn
935 (delete-region start end) 949 (delete-region start end)
936 (insert word))) 950 (setq start (point))
937 (if (not (atom replace)) ; recheck spelling of replacement 951 (insert new-word)
952 (setq end (point))))
953 (if (not (atom replace)) ;recheck spelling of replacement
938 (progn 954 (progn
939 (goto-char cursor-location) 955 (if (car (cdr replace)) ; query replace requested
940 (ispell-word following quietly))))) 956 (save-window-excursion
957 (query-replace word new-word t)))
958 (ispell-region start end)))))
941 (if (get-buffer ispell-choices-buffer) 959 (if (get-buffer ispell-choices-buffer)
942 (kill-buffer ispell-choices-buffer)))) 960 (kill-buffer ispell-choices-buffer))))
943 (goto-char cursor-location) ; return to original location 961 (goto-char cursor-location) ; return to original location
@@ -960,8 +978,8 @@ Word syntax described by `ispell-dictionary-alist' (which see)."
960 (ispell-many-otherchars-p (ispell-get-many-otherchars-p)) 978 (ispell-many-otherchars-p (ispell-get-many-otherchars-p))
961 (word-regexp (concat ispell-casechars 979 (word-regexp (concat ispell-casechars
962 "+\\(" 980 "+\\("
963 ispell-otherchars 981 (if (not (string= "" ispell-otherchars))
964 "?" 982 (concat ispell-otherchars "?"))
965 (if extra-otherchars 983 (if extra-otherchars
966 (concat extra-otherchars "?")) 984 (concat extra-otherchars "?"))
967 ispell-casechars 985 ispell-casechars
@@ -969,7 +987,7 @@ Word syntax described by `ispell-dictionary-alist' (which see)."
969 (if (or ispell-many-otherchars-p 987 (if (or ispell-many-otherchars-p
970 extra-otherchars) 988 extra-otherchars)
971 "*" "?"))) 989 "*" "?")))
972 did-it-once 990 did-it-once prevpt
973 start end word) 991 start end word)
974 ;; find the word 992 ;; find the word
975 (if (not (looking-at ispell-casechars)) 993 (if (not (looking-at ispell-casechars))
@@ -978,17 +996,20 @@ Word syntax described by `ispell-dictionary-alist' (which see)."
978 (re-search-backward ispell-casechars (point-min) t))) 996 (re-search-backward ispell-casechars (point-min) t)))
979 ;; move to front of word 997 ;; move to front of word
980 (re-search-backward ispell-not-casechars (point-min) 'start) 998 (re-search-backward ispell-not-casechars (point-min) 'start)
981 (while (and (or (looking-at ispell-otherchars) 999 (while (and (or (and (not (string= "" ispell-otherchars))
1000 (looking-at ispell-otherchars))
982 (and extra-otherchars (looking-at extra-otherchars))) 1001 (and extra-otherchars (looking-at extra-otherchars)))
983 (not (bobp)) 1002 (not (bobp))
984 (or (not did-it-once) 1003 (or (not did-it-once)
985 ispell-many-otherchars-p)) 1004 ispell-many-otherchars-p)
1005 (not (eq prevpt (point))))
986 (if (and extra-otherchars (looking-at extra-otherchars)) 1006 (if (and extra-otherchars (looking-at extra-otherchars))
987 (progn 1007 (progn
988 (backward-char 1) 1008 (backward-char 1)
989 (if (looking-at ispell-casechars) 1009 (if (looking-at ispell-casechars)
990 (re-search-backward ispell-not-casechars (point-min) 'move))) 1010 (re-search-backward ispell-not-casechars (point-min) 'move)))
991 (setq did-it-once t) 1011 (setq did-it-once t
1012 prevpt (point))
992 (backward-char 1) 1013 (backward-char 1)
993 (if (looking-at ispell-casechars) 1014 (if (looking-at ispell-casechars)
994 (re-search-backward ispell-not-casechars (point-min) 'move) 1015 (re-search-backward ispell-not-casechars (point-min) 'move)
@@ -996,6 +1017,7 @@ Word syntax described by `ispell-dictionary-alist' (which see)."
996 ;; Now mark the word and save to string. 1017 ;; Now mark the word and save to string.
997 (if (not (re-search-forward word-regexp (point-max) t)) 1018 (if (not (re-search-forward word-regexp (point-max) t))
998 (if ispell-check-only 1019 (if ispell-check-only
1020 ;; return dummy word when just flagging misspellings
999 (list "" (point) (point)) 1021 (list "" (point) (point))
1000 (error "No word found to check!")) 1022 (error "No word found to check!"))
1001 (setq start (match-beginning 0) 1023 (setq start (match-beginning 0)
@@ -1009,6 +1031,7 @@ Word syntax described by `ispell-dictionary-alist' (which see)."
1009;;; a value or a list, whose value is the state of whether the 1031;;; a value or a list, whose value is the state of whether the
1010;;; dictionary needs to be saved. 1032;;; dictionary needs to be saved.
1011 1033
1034;;; ###autoload
1012(defun ispell-pdict-save (&optional no-query force-save) 1035(defun ispell-pdict-save (&optional no-query force-save)
1013 "Check to see if the personal dictionary has been modified. 1036 "Check to see if the personal dictionary has been modified.
1014If so, ask if it needs to be saved." 1037If so, ask if it needs to be saved."
@@ -1031,10 +1054,13 @@ Returns nil to keep word.
1031Returns 0 to insert locally into buffer-local dictionary. 1054Returns 0 to insert locally into buffer-local dictionary.
1032Returns string for new chosen word. 1055Returns string for new chosen word.
1033Returns list for new replacement word (will be rechecked). 1056Returns list for new replacement word (will be rechecked).
1057 Query-replace when list length is 2.
1058 Automatic query-replace when second element is `query-replace'.
1034Highlights the word, which is assumed to run from START to END. 1059Highlights the word, which is assumed to run from START to END.
1035Global `ispell-pdict-modified-p' becomes a list where the only value 1060Global `ispell-pdict-modified-p' becomes a list where the only value
1036indicates whether the dictionary has been modified when option `a' or `i' is 1061indicates whether the dictionary has been modified when option `a' or `i' is
1037used." 1062used.
1063Global `ispell-quit' set to start location to continue spell session."
1038 (let ((textbuf (current-buffer)) 1064 (let ((textbuf (current-buffer))
1039 (count ?0) 1065 (count ?0)
1040 (line 2) 1066 (line 2)
@@ -1043,15 +1069,16 @@ used."
1043 (window-min-height (min window-min-height 1069 (window-min-height (min window-min-height
1044 ispell-choices-win-default-height)) 1070 ispell-choices-win-default-height))
1045 (command-characters '( ? ?i ?a ?A ?r ?R ?? ?x ?X ?q ?l ?u ?m )) 1071 (command-characters '( ? ?i ?a ?A ?r ?R ?? ?x ?X ?q ?l ?u ?m ))
1046 (skipped 0)
1047 (window (selected-window))
1048 (dedicated (window-dedicated-p (selected-window))) 1072 (dedicated (window-dedicated-p (selected-window)))
1049 char num result textwin highlighted) 1073 (skipped 0)
1074 char num result textwin dedicated-win highlighted)
1050 1075
1051 ;; setup the *Choices* buffer with valid data. 1076 ;; setup the *Choices* buffer with valid data.
1052 (save-excursion 1077 (save-excursion
1053 (set-buffer (get-buffer-create ispell-choices-buffer)) 1078 (set-buffer (get-buffer-create ispell-choices-buffer))
1054 (setq mode-line-format (concat "-- %b -- word: " word)) 1079 (setq mode-line-format (concat "-- %b -- word: " word))
1080 (and (fboundp 'set-specifier) ; prevent XEmacs modeline hiding
1081 (set-specifier has-modeline-p (cons (current-buffer) nil)))
1055 (erase-buffer) 1082 (erase-buffer)
1056 (if guess 1083 (if guess
1057 (progn 1084 (progn
@@ -1080,48 +1107,33 @@ used."
1080 ;; not so good if there are over 20 or 30 options, but then, if 1107 ;; not so good if there are over 20 or 30 options, but then, if
1081 ;; there are that many you don't want to scan them all anyway... 1108 ;; there are that many you don't want to scan them all anyway...
1082 (while (memq count command-characters) ; skip command characters. 1109 (while (memq count command-characters) ; skip command characters.
1083 (setq count (1+ count) 1110 (setq count (ispell-int-char (1+ count))
1084 skipped (1+ skipped))) 1111 skipped (1+ skipped)))
1085 (insert "(" count ") " (car choices) " ") 1112 (insert "(" count ") " (car choices) " ")
1086 (setq choices (cdr choices) 1113 (setq choices (cdr choices)
1087 count (1+ count))) 1114 count (ispell-int-char (1+ count))))
1088 (setq count (- count ?0 skipped))) 1115 (setq count (ispell-int-char (- count ?0 skipped))))
1089 1116
1090 ;; Assure word is visible 1117 ;; Assure word is visible
1091 (if (not (pos-visible-in-window-p end)) 1118 (if (not (pos-visible-in-window-p end))
1092 (sit-for 0)) 1119 (sit-for 0))
1120
1121 ;; allow temporary split of dedicated windows...
1122 (if dedicated
1123 (progn
1124 (setq dedicated-win (selected-window))
1125 (set-window-dedicated-p dedicated-win nil)))
1126
1093 ;; Display choices for misspelled word. 1127 ;; Display choices for misspelled word.
1094 (let ((choices-window (get-buffer-window ispell-choices-buffer))) 1128 (ispell-show-choices line end)
1095 (if choices-window
1096 (if (= line (window-height choices-window))
1097 (select-window choices-window)
1098 ;; *Choices* window changed size. Adjust the choices window
1099 ;; without scrolling the spelled window when possible
1100 (let ((window-line (- line (window-height choices-window)))
1101 (visible (progn (forward-line -1) (point))))
1102 (if (< line ispell-choices-win-default-height)
1103 (setq window-line (+ window-line
1104 (- ispell-choices-win-default-height
1105 line))))
1106 (move-to-window-line 0)
1107 (forward-line window-line)
1108 (set-window-start (selected-window)
1109 (if (> (point) visible) visible (point)))
1110 (goto-char end)
1111 (select-window (previous-window)) ; *Choices* window
1112 (enlarge-window window-line)))
1113 ;; Overlay *Choices* window when it isn't showing
1114 (ispell-overlay-window (max line ispell-choices-win-default-height)))
1115 (switch-to-buffer ispell-choices-buffer)
1116 (goto-char (point-min)))
1117 1129
1118 (select-window (setq textwin (next-window))) 1130 (select-window (setq textwin (next-window)))
1119 1131
1120 ;; highlight word, protecting current buffer status 1132 ;; highlight word, protecting current buffer status
1121 (unwind-protect 1133 (unwind-protect
1122 (progn 1134 (progn
1123 (if ispell-highlight-p 1135 (and ispell-highlight-p
1124 (ispell-highlight-spelling-error start end t)) 1136 (ispell-highlight-spelling-error start end t))
1125 ;; Loop until a valid choice is made. 1137 ;; Loop until a valid choice is made.
1126 (while 1138 (while
1127 (eq 1139 (eq
@@ -1162,11 +1174,25 @@ used."
1162 (list ispell-pdict-modified-p))) 1174 (list ispell-pdict-modified-p)))
1163 (if (= char ?A) 0)) ; return 0 for ispell-add buffer-local 1175 (if (= char ?A) 0)) ; return 0 for ispell-add buffer-local
1164 ((or (= char ?r) (= char ?R)) ; type in replacement 1176 ((or (= char ?r) (= char ?R)) ; type in replacement
1165 (if (or (= char ?R) ispell-query-replace-choices) 1177 (and (eq 'block ispell-highlight-p) ; refresh tty's
1166 (list (read-string "Query-replacement for: " word) t) 1178 (ispell-highlight-spelling-error start end nil t))
1167 (cons (read-string "Replacement for: " word) nil))) 1179 (let ((result
1180 (if (or (= char ?R) ispell-query-replace-choices)
1181 (list (read-string "Query-replacement for: "
1182 word) t)
1183 (cons (read-string "Replacement for: " word)
1184 nil))))
1185 (and (eq 'block ispell-highlight-p)
1186 (ispell-highlight-spelling-error start end nil
1187 'block))
1188 result))
1168 ((or (= char ??) (= char help-char) (= char ?\C-h)) 1189 ((or (= char ??) (= char help-char) (= char ?\C-h))
1190 (and (eq 'block ispell-highlight-p)
1191 (ispell-highlight-spelling-error start end nil t))
1169 (ispell-help) 1192 (ispell-help)
1193 (and (eq 'block ispell-highlight-p)
1194 (ispell-highlight-spelling-error start end nil
1195 'block))
1170 t) 1196 t)
1171 ;; Quit and move point back. 1197 ;; Quit and move point back.
1172 ((= char ?x) 1198 ((= char ?x)
@@ -1181,8 +1207,7 @@ used."
1181 (substitute-command-keys 1207 (substitute-command-keys
1182 (concat "Spell-checking suspended;" 1208 (concat "Spell-checking suspended;"
1183 " use C-u \\[ispell-word] to resume"))) 1209 " use C-u \\[ispell-word] to resume")))
1184 (setq ispell-quit (max (point-min) 1210 (setq ispell-quit start)
1185 (- (point) (length word))))
1186 nil) 1211 nil)
1187 ((= char ?q) 1212 ((= char ?q)
1188 (if (y-or-n-p "Really kill Ispell process? ") 1213 (if (y-or-n-p "Really kill Ispell process? ")
@@ -1193,6 +1218,8 @@ used."
1193 ispell-pdict-modified-p nil)) 1218 ispell-pdict-modified-p nil))
1194 t)) ; continue if they don't quit. 1219 t)) ; continue if they don't quit.
1195 ((= char ?l) 1220 ((= char ?l)
1221 (and (eq 'block ispell-highlight-p) ; refresh tty displays
1222 (ispell-highlight-spelling-error start end nil t))
1196 (let ((new-word (read-string 1223 (let ((new-word (read-string
1197 "Lookup string (`*' is wildcard): " 1224 "Lookup string (`*' is wildcard): "
1198 word)) 1225 word))
@@ -1222,12 +1249,13 @@ used."
1222 new-line) 1249 new-line)
1223 max-lines)) 1250 max-lines))
1224 (while (memq count command-characters) 1251 (while (memq count command-characters)
1225 (setq count (1+ count) 1252 (setq count (ispell-int-char (1+ count))
1226 skipped (1+ skipped))) 1253 skipped (1+ skipped)))
1227 (insert "(" count ") " (car choices) " ") 1254 (insert "(" count ") " (car choices) " ")
1228 (setq choices (cdr choices) 1255 (setq choices (cdr choices)
1229 count (1+ count))) 1256 count (ispell-int-char (1+ count))))
1230 (setq count (- count ?0 skipped))) 1257 (setq count (ispell-int-char
1258 (- count ?0 skipped))))
1231 (select-window (previous-window)) 1259 (select-window (previous-window))
1232 (if (and (/= new-line line) 1260 (if (and (/= new-line line)
1233 (> (max line new-line) 1261 (> (max line new-line)
@@ -1244,6 +1272,9 @@ used."
1244 (shrink-window (- line new-line shr-bl))) 1272 (shrink-window (- line new-line shr-bl)))
1245 (setq line new-line))) 1273 (setq line new-line)))
1246 (select-window (next-window))))) 1274 (select-window (next-window)))))
1275 (and (eq 'block ispell-highlight-p)
1276 (ispell-highlight-spelling-error start end nil
1277 'block))
1247 t) ; reselect from new choices 1278 t) ; reselect from new choices
1248 ((= char ?u) 1279 ((= char ?u)
1249 (process-send-string ispell-process 1280 (process-send-string ispell-process
@@ -1263,18 +1294,72 @@ used."
1263 ((= char ?\C-l) 1294 ((= char ?\C-l)
1264 (redraw-display) t) 1295 (redraw-display) t)
1265 ((= char ?\C-r) 1296 ((= char ?\C-r)
1266 (save-window-excursion (recursive-edit)) t) 1297 (if (marker-position ispell-recursive-edit-marker)
1298 (progn
1299 (message "Only one recursive edit session supported")
1300 (beep))
1301 (set-marker ispell-recursive-edit-marker start)
1302 ;;(set-marker ispell-region-end reg-end)
1303 (and ispell-highlight-p ; unhighlight
1304 (ispell-highlight-spelling-error start end))
1305 (unwind-protect
1306 (progn
1307 (save-window-excursion (save-excursion
1308 (recursive-edit)) t)
1309 (if (not (equal (marker-buffer
1310 ispell-recursive-edit-marker)
1311 (current-buffer)))
1312 (error
1313 "Cannot continue ispell from this buffer."))
1314 (goto-char ispell-recursive-edit-marker))
1315 (set-marker ispell-recursive-edit-marker nil)))
1316 (cons word nil)) ; recheck starting at this word.
1267 ((= char ?\C-z) 1317 ((= char ?\C-z)
1268 (funcall (key-binding "\C-z")) 1318 (funcall (key-binding "\C-z"))
1269 t) 1319 t)
1270 (t (ding) t)))))) 1320 (t (ding) t))))))
1271 result) 1321 result)
1272 ;; protected 1322 ;; protected
1273 (if ispell-highlight-p ; unhighlight 1323 (and ispell-highlight-p ; unhighlight
1274 (save-window-excursion 1324 (save-window-excursion
1275 (select-window textwin) 1325 (select-window textwin)
1276 (ispell-highlight-spelling-error start end))) 1326 (ispell-highlight-spelling-error start end)))
1277 (set-window-dedicated-p window dedicated)))) 1327 (if dedicated
1328 (set-window-dedicated-p dedicated-win t)))))
1329
1330
1331
1332(defun ispell-show-choices (line end)
1333 "Shows the choices in another buffer or frame."
1334 (if ispell-use-framepop-p
1335 (progn
1336 (framepop-display-buffer (get-buffer ispell-choices-buffer))
1337 (get-buffer-window ispell-choices-buffer t)
1338 (select-window (previous-window))) ; *Choices* window
1339 ;; standard selection by splitting a small buffer out of this window.
1340 (let ((choices-window (get-buffer-window ispell-choices-buffer)))
1341 (if choices-window
1342 (if (= line (window-height choices-window))
1343 (select-window choices-window)
1344 ;; *Choices* window changed size. Adjust the choices window
1345 ;; without scrolling the spelled window when possible
1346 (let ((window-line (- line (window-height choices-window)))
1347 (visible (progn (vertical-motion -1) (point))))
1348 (if (< line ispell-choices-win-default-height)
1349 (setq window-line (+ window-line
1350 (- ispell-choices-win-default-height
1351 line))))
1352 (move-to-window-line 0)
1353 (vertical-motion window-line)
1354 (set-window-start (selected-window)
1355 (if (> (point) visible) visible (point)))
1356 (goto-char end)
1357 (select-window (previous-window)) ; *Choices* window
1358 (enlarge-window window-line)))
1359 ;; Overlay *Choices* window when it isn't showing
1360 (ispell-overlay-window (max line ispell-choices-win-default-height)))
1361 (switch-to-buffer ispell-choices-buffer)
1362 (goto-char (point-min)))))
1278 1363
1279 1364
1280;;;###autoload 1365;;;###autoload
@@ -1297,45 +1382,77 @@ SPC: Accept word this time.
1297`q': Quit spelling session (Kills ispell process). 1382`q': Quit spelling session (Kills ispell process).
1298`l': Look up typed-in replacement in alternate dictionary. Wildcards okay. 1383`l': Look up typed-in replacement in alternate dictionary. Wildcards okay.
1299`u': Like `i', but the word is lower-cased first. 1384`u': Like `i', but the word is lower-cased first.
1300`m': Like `i', but allows one to include dictionary completion information. 1385`m': Place typed-in value in personal dictionary, then recheck current word.
1301`C-l': redraws screen 1386`C-l': redraws screen
1302`C-r': recursive edit 1387`C-r': recursive edit
1303`C-z': suspend emacs or iconify frame" 1388`C-z': suspend emacs or iconify frame"
1304 1389
1305 (let ((help-1 (concat "[r/R]eplace word; [a/A]ccept for this session; " 1390 (if (equal ispell-help-in-bufferp 'electric)
1306 "[i]nsert into private dictionary")) 1391 (progn
1307 (help-2 (concat "[l]ook a word up in alternate dictionary; " 1392 (require 'ehelp)
1308 "e[x/X]it; [q]uit session")) 1393 (with-electric-help
1309 (help-3 (concat "[u]ncapitalized insert into dictionary. " 1394 (function (lambda ()
1310 "Type 'C-h d ispell-help' for more help"))) 1395 ;;This shouldn't be necessary: with-electric-help needs
1311 (save-window-excursion 1396 ;; an optional argument telling it about the smallest
1312 (if ispell-help-in-bufferp 1397 ;; acceptable window-height of the help buffer.
1313 (progn 1398 (if (< (window-height) 15)
1314 (ispell-overlay-window 4) 1399 (enlarge-window (- 15 (window-height))))
1315 (switch-to-buffer (get-buffer-create "*Ispell Help*")) 1400 (princ "Selections are:
1316 (insert (concat help-1 "\n" help-2 "\n" help-3)) 1401
1317 (sit-for 5) 1402DIGIT: Replace the word with a digit offered in the *Choices* buffer.
1318 (kill-buffer "*Ispell Help*")) 1403SPC: Accept word this time.
1319 (select-window (minibuffer-window)) 1404`i': Accept word and insert into private dictionary.
1320 ;;(enlarge-window 2) 1405`a': Accept word for this session.
1321 (erase-buffer) 1406`A': Accept word and place in `buffer-local dictionary'.
1322 (cond ((string-match "Lucid" emacs-version) 1407`r': Replace word with typed-in value. Rechecked.
1323 (message help-3) 1408`R': Replace word with typed-in value. Query-replaced in buffer. Rechecked.
1324 (enlarge-window 1) 1409`?': Show these commands.
1325 (message help-2) 1410`x': Exit spelling buffer. Move cursor to original point.
1326 (enlarge-window 1) 1411`X': Exit spelling buffer. Leaves cursor at the current point, and permits
1327 (message help-1) 1412 the aborted check to be completed later.
1328 (goto-char (point-min))) 1413`q': Quit spelling session (Kills ispell process).
1329 (t 1414`l': Look up typed-in replacement in alternate dictionary. Wildcards okay.
1330 (if (string-lessp "19" emacs-version) 1415`u': Like `i', but the word is lower-cased first.
1331 (message nil)) 1416`m': Place typed-in value in personal dictionary, then recheck current word.
1332 (enlarge-window 2) 1417`C-l': redraws screen
1333 ;; Make sure we display the minibuffer 1418`C-r': recursive edit
1334 ;; in this window, not some other. 1419`C-z': suspend emacs or iconify frame")
1335 (set-minibuffer-window (selected-window)) 1420 nil ;undocumented requirement of with-electric-help
1336 (insert (concat help-1 "\n" help-2 "\n" help-3)))) 1421 ))))
1337 (sit-for 5) 1422
1338 (erase-buffer))))) 1423
1424 (let ((help-1 (concat "[r/R]eplace word; [a/A]ccept for this session; "
1425 "[i]nsert into private dictionary"))
1426 (help-2 (concat "[l]ook a word up in alternate dictionary; "
1427 "e[x/X]it; [q]uit session"))
1428 (help-3 (concat "[u]ncapitalized insert into dict. "
1429 "Type 'x C-h d ispell-help' for more help")))
1430 (save-window-excursion
1431 (if ispell-help-in-bufferp
1432 (progn
1433 (ispell-overlay-window 4)
1434 (switch-to-buffer (get-buffer-create "*Ispell Help*"))
1435 (insert (concat help-1 "\n" help-2 "\n" help-3))
1436 (sit-for 5)
1437 (kill-buffer "*Ispell Help*"))
1438 (select-window (minibuffer-window))
1439 ;;(enlarge-window 2)
1440 (erase-buffer)
1441 (cond ((string-match "Lucid\\|XEmacs" emacs-version)
1442 (message help-3)
1443 (enlarge-window 1)
1444 (message help-2)
1445 (enlarge-window 1)
1446 (message help-1)
1447 (goto-char (point-min)))
1448 (t
1449 (if (not (string-match "18\\.[0-9]+\\.[0-9]+" emacs-version))
1450 (message nil))
1451 ;;(set-minibuffer-window (selected-window))
1452 (enlarge-window 2)
1453 (insert (concat help-1 "\n" help-2 "\n" help-3))))
1454 (sit-for 5)
1455 (erase-buffer))))))
1339 1456
1340 1457
1341(defun lookup-words (word &optional lookup-dict) 1458(defun lookup-words (word &optional lookup-dict)
@@ -1384,7 +1501,8 @@ Optional second argument contains the dictionary to use; the default is
1384 (while (not (bobp)) 1501 (while (not (bobp))
1385 (setq loc (point)) 1502 (setq loc (point))
1386 (forward-line -1) 1503 (forward-line -1)
1387 (setq results (cons (buffer-substring (point) (1- loc)) 1504 (setq results (cons (buffer-substring-no-properties (point)
1505 (1- loc))
1388 results))))) 1506 results)))))
1389 ;; protected 1507 ;; protected
1390 (kill-buffer ispell-grep-buffer) 1508 (kill-buffer ispell-grep-buffer)
@@ -1436,15 +1554,23 @@ Optional second argument contains the dictionary to use; the default is
1436 1554
1437;;; This function destroys the mark location if it is in the word being 1555;;; This function destroys the mark location if it is in the word being
1438;;; highlighted. 1556;;; highlighted.
1439(defun ispell-highlight-spelling-error-generic (start end &optional highlight) 1557(defun ispell-highlight-spelling-error-generic (start end &optional highlight
1558 refresh)
1440 "Highlight the word from START to END with a kludge using `inverse-video'. 1559 "Highlight the word from START to END with a kludge using `inverse-video'.
1441When the optional third arg HIGHLIGHT is set, the word is highlighted; 1560When the optional third arg HIGHLIGHT is set, the word is highlighted;
1442otherwise it is displayed normally." 1561otherwise it is displayed normally.
1562Uses block cursor to highlight one charcater.
1563Optional REFRESH will unhighlighted then highlight, using block cursor
1564 highlighting when REFRESH is equal to `block'."
1565 (and (eq 'block ispell-highlight-p)
1566 (or (eq 'block refresh)
1567 (setq start (1+ start)))) ; On block non-refresh, inc start.
1443 (let ((modified (buffer-modified-p)) ; don't allow this fn to modify buffer 1568 (let ((modified (buffer-modified-p)) ; don't allow this fn to modify buffer
1444 (buffer-read-only nil) ; Allow highlighting read-only buffers. 1569 (buffer-read-only nil) ; Allow highlighting read-only buffers.
1445 (text (buffer-substring start end)) ; Save highlight region 1570 (text (buffer-substring-no-properties start end)) ; Save hilight region
1446 (inhibit-quit t) ; inhibit interrupt processing here. 1571 (inhibit-quit t) ; inhibit interrupt processing here.
1447 (buffer-undo-list t)) ; don't clutter the undo list. 1572 (buffer-undo-list t)) ; don't clutter the undo list.
1573 (goto-char end)
1448 (delete-region start end) 1574 (delete-region start end)
1449 (insert-char ? (- end start)) ; minimize amount of redisplay 1575 (insert-char ? (- end start)) ; minimize amount of redisplay
1450 (sit-for 0) ; update display 1576 (sit-for 0) ; update display
@@ -1452,11 +1578,18 @@ otherwise it is displayed normally."
1452 (delete-region start end) ; delete whitespace 1578 (delete-region start end) ; delete whitespace
1453 (insert text) ; insert text in inverse video. 1579 (insert text) ; insert text in inverse video.
1454 (sit-for 0) ; update display showing inverse video. 1580 (sit-for 0) ; update display showing inverse video.
1455 (if highlight (setq inverse-video (not inverse-video))) ; toggle video 1581 (if (not highlight)
1456 (set-buffer-modified-p modified))) ; don't modify if flag not set. 1582 (goto-char end)
1457 1583 (setq inverse-video (not inverse-video)) ; toggle video
1458 1584 (and (eq 'block ispell-highlight-p)
1459(defun ispell-highlight-spelling-error-lucid (start end &optional highlight) 1585 (goto-char (1- start)))) ; use block cursor to "highlight" char
1586 (set-buffer-modified-p modified) ; don't modify if flag not set.
1587 (and refresh ; re-highlight
1588 (ispell-highlight-spelling-error-generic
1589 (if (eq 'block refresh) start (- start 2)) end t))))
1590
1591
1592(defun ispell-highlight-spelling-error-xemacs (start end &optional highlight)
1460 "Highlight the word from START to END using `isearch-highlight'. 1593 "Highlight the word from START to END using `isearch-highlight'.
1461When the optional third arg HIGHLIGHT is set, the word is highlighted, 1594When the optional third arg HIGHLIGHT is set, the word is highlighted,
1462otherwise it is displayed normally." 1595otherwise it is displayed normally."
@@ -1480,14 +1613,14 @@ The variable `ispell-highlight-face' selects the face to use for highlighting."
1480 (delete-overlay ispell-overlay))) 1613 (delete-overlay ispell-overlay)))
1481 1614
1482 1615
1483(defun ispell-highlight-spelling-error (start end &optional highlight) 1616(defun ispell-highlight-spelling-error (start end &optional highlight refresh)
1484 (cond 1617 (cond
1485 ((string-match "Lucid" emacs-version) 1618 ((string-match "Lucid\\|XEmacs" emacs-version)
1486 (ispell-highlight-spelling-error-lucid start end highlight)) 1619 (ispell-highlight-spelling-error-xemacs start end highlight))
1487 ((and (string-lessp "19" emacs-version) 1620 ((and (not (string-match "18\\.[0-9]+\\.[0-9]+" emacs-version))
1488 (featurep 'faces) window-system) 1621 (featurep 'faces) window-system)
1489 (ispell-highlight-spelling-error-overlay start end highlight)) 1622 (ispell-highlight-spelling-error-overlay start end highlight))
1490 (t (ispell-highlight-spelling-error-generic start end highlight)))) 1623 (t (ispell-highlight-spelling-error-generic start end highlight refresh))))
1491 1624
1492 1625
1493(defun ispell-overlay-window (height) 1626(defun ispell-overlay-window (height)
@@ -1501,38 +1634,45 @@ scrolling the current window. Leave the new window selected."
1501 ;; hidden by new window, scroll it to just below new win 1634 ;; hidden by new window, scroll it to just below new win
1502 ;; otherwise set top line of other win so it doesn't scroll. 1635 ;; otherwise set top line of other win so it doesn't scroll.
1503 (if (< oldot top) (setq top oldot)) 1636 (if (< oldot top) (setq top oldot))
1504 ;; NB: Lemacs 19.9 bug: If a window of size N (N includes the mode 1637 ;; NB: XEmacs 19.9 bug: If a window of size N (N includes the mode
1505 ;; line) is demanded, the last line is not visible. 1638 ;; line) is demanded, the last line is not visible.
1506 ;; At least this happens on AIX 3.2, lemacs w/ Motif, font 9x15. 1639 ;; At least this happens on AIX 3.2, XEmacs w/ Motif, font 9x15.
1507 ;; So we increment the height for this case. 1640 ;; So we increment the height for this case.
1508 (if (string-match "19\.9.*Lucid" (emacs-version)) 1641 (if (and (string-match "Lucid\\|XEmacs" emacs-version)
1642 (string-match "19\\.9\\.[0-9]+" emacs-version))
1509 (setq height (1+ height))) 1643 (setq height (1+ height)))
1510 (split-window nil height) 1644 ;; if frame is unsplitable, temporarily disable that...
1511 ;; The lower of the two windows is the logical successor 1645 (if (cdr (assq 'unsplittable (frame-parameters (selected-frame))))
1512 ;; of the original window, so move the dedicated flag to there. 1646 (let ((frame (selected-frame)))
1513 ;; The new upper window should not be dedicated. 1647 (modify-frame-parameters frame '((unsplittable . nil)))
1514 (set-window-dedicated-p (next-window) 1648 (split-window nil height)
1515 (window-dedicated-p (selected-window))) 1649 (modify-frame-parameters frame '((unsplittable . t))))
1516 (set-window-dedicated-p (selected-window) nil) 1650 (split-window nil height))
1517 (set-window-start (next-window) top)))) 1651 (set-window-start (next-window) top))))
1518 1652
1519 1653
1520;;; Should we add a compound word match return value? 1654;;; Should we add a compound word match return value?
1521(defun ispell-parse-output (output) 1655(defun ispell-parse-output (output)
1522 "Parse the OUTPUT string from Ispell and return: 1656 "Parse the OUTPUT string from Ispell process and return:
15231: t for an exact match. 16571: t for an exact match.
15242: A string containing the root word for a match via suffix removal. 16582: A string containing the root word matched via suffix removal.
15253: A list of possible correct spellings of the format: 16593: A list of possible correct spellings of the format:
1526 '(\"ORIGINAL-WORD\" OFFSET MISS-LIST GUESS-LIST) 1660 (\"ORIGINAL-WORD\" OFFSET MISS-LIST GUESS-LIST)
1527 ORIGINAL-WORD is a string of the possibly misspelled word. 1661 ORIGINAL-WORD is a string of the possibly misspelled word.
1528 OFFSET is an integer giving the line offset of the word. 1662 OFFSET is an integer giving the line offset of the word.
1529 MISS-LIST and GUESS-LIST are possibly null lists of guesses and misses." 1663 MISS-LIST and GUESS-LIST are possibly null lists of guesses and misses.
16644: Nil when an error has occurred."
1530 (cond 1665 (cond
1531 ((string= output "") t) ; for startup with pipes... 1666 ((string= output "") t) ; for startup with pipes...
1532 ((string= output "*") t) ; exact match 1667 ((string= output "*") t) ; exact match
1533 ((string= output "-") t) ; compound word match 1668 ((string= output "-") t) ; compound word match
1534 ((string= (substring output 0 1) "+") ; found cuz of root word 1669 ((string= (substring output 0 1) "+") ; found because of root word
1535 (substring output 2)) ; return root word 1670 (substring output 2)) ; return root word
1671 ((equal 0 (string-match "[\ a-zA-Z]" output))
1672 (ding) ; error message from ispell!
1673 (message (concat "Ispell error: " output))
1674 (sit-for 5)
1675 nil)
1536 (t ; need to process &, ?, and #'s 1676 (t ; need to process &, ?, and #'s
1537 (let ((type (substring output 0 1)) ; &, ?, or # 1677 (let ((type (substring output 0 1)) ; &, ?, or #
1538 (original-word (substring output 2 (string-match " " output 2))) 1678 (original-word (substring output 2 (string-match " " output 2)))
@@ -1559,7 +1699,7 @@ scrolling the current window. Leave the new window selected."
1559 (list original-word offset miss-list guess-list))))) 1699 (list original-word offset miss-list guess-list)))))
1560 1700
1561 1701
1562(defun check-ispell-version () 1702(defun check-ispell-version (&optional interactivep)
1563 ;; This is a little wasteful as we actually launch ispell twice: once 1703 ;; This is a little wasteful as we actually launch ispell twice: once
1564 ;; to make sure it's the right version, and once for real. But people 1704 ;; to make sure it's the right version, and once for real. But people
1565 ;; get confused by version mismatches *all* the time (and I've got the 1705 ;; get confused by version mismatches *all* the time (and I've got the
@@ -1567,32 +1707,44 @@ scrolling the current window. Leave the new window selected."
1567 ;; option is the only way I can think of to do this that works with 1707 ;; option is the only way I can think of to do this that works with
1568 ;; all versions, since versions earlier than 3.0.09 didn't identify 1708 ;; all versions, since versions earlier than 3.0.09 didn't identify
1569 ;; themselves on startup. 1709 ;; themselves on startup.
1710 (interactive "p")
1570 (save-excursion 1711 (save-excursion
1571 (let ((case-fold-search t) 1712 (let (case-fold-search status
1572 ;; avoid bugs when syntax of `.' changes in various default modes 1713 ;; avoid bugs when syntax of `.' changes in various default modes
1573 (default-major-mode 'fundamental-mode) 1714 (default-major-mode 'fundamental-mode)
1574 status) 1715 (result t))
1575 (set-buffer (get-buffer-create " *ispell-tmp*")) 1716 (set-buffer (get-buffer-create " *ispell-tmp*"))
1717 (setq case-fold-search t)
1576 (erase-buffer) 1718 (erase-buffer)
1577 (setq status (call-process ispell-program-name nil t nil "-v")) 1719 (setq status (call-process ispell-program-name nil t nil "-v"))
1578 (goto-char (point-min)) 1720 (goto-char (point-min))
1721 (if interactivep
1722 (progn
1723 (end-of-line)
1724 (setq result (concat (buffer-substring-no-properties (point-min)
1725 (point))
1726 ", "
1727 ispell-version))
1728 (message result)
1729 (goto-char (point-min))))
1579 (if (not (memq status '(0 nil))) 1730 (if (not (memq status '(0 nil)))
1580 (error "%s exited with %s %s" ispell-program-name 1731 (error "%s exited with %s %s" ispell-program-name
1581 (if (stringp status) "signal" "code") status)) 1732 (if (stringp status) "signal" "code") status))
1582 (if (not (re-search-forward 1733 (if (not (re-search-forward
1583 (concat "\\b\\(" 1734 (concat "\\<\\("
1584 (regexp-quote (car ispell-required-version)) 1735 (regexp-quote (car ispell-required-version))
1585 "\\)\\([0-9]*\\)\\b") 1736 "\\)\\([0-9]*\\)\\>")
1586 nil t)) 1737 nil t))
1587 (error 1738 (error "%s version 3 release %s%s or greater is required"
1588 "%s version %s* is required: try renaming ispell4.el to ispell.el" 1739 ispell-program-name (car ispell-required-version)
1589 ispell-program-name (car ispell-required-version)) 1740 (car (cdr ispell-required-version)))
1590 ;; check that it is the correct version. 1741 ;; check that it is the correct version.
1591 (if (< (car (read-from-string (buffer-substring 1742 (if (< (car (read-from-string (buffer-substring-no-properties
1592 (match-beginning 2) (match-end 2)))) 1743 (match-beginning 2) (match-end 2))))
1593 (car (cdr ispell-required-version))) 1744 (car (cdr ispell-required-version)))
1594 (setq ispell-offset 0))) 1745 (setq ispell-offset 0)))
1595 (kill-buffer (current-buffer))))) 1746 (kill-buffer (current-buffer))
1747 result)))
1596 1748
1597 1749
1598(defun ispell-init-process () 1750(defun ispell-init-process ()
@@ -1635,17 +1787,25 @@ scrolling the current window. Leave the new window selected."
1635 ispell-filter-continue nil 1787 ispell-filter-continue nil
1636 ispell-process-directory default-directory) 1788 ispell-process-directory default-directory)
1637 (set-process-filter ispell-process 'ispell-filter) 1789 (set-process-filter ispell-process 'ispell-filter)
1638 (if (and enable-multibyte-characters 1790 (if (and (boundp 'enable-multibyte-characters)
1639 ispell-dictionary) 1791 (fboundp 'set-process-coding-system)
1792 enable-multibyte-characters)
1640 (set-process-coding-system ispell-process (ispell-get-coding-system))) 1793 (set-process-coding-system ispell-process (ispell-get-coding-system)))
1641 (accept-process-output ispell-process) ; Get version ID line 1794 ;; Get version ID line
1795 (if (not (string-match "18\\.[0-9]+\\.[0-9]+" emacs-version))
1796 (accept-process-output ispell-process 5)
1797 (accept-process-output ispell-process))
1798 ;; get more output if filter empty?
1799 (if (null ispell-filter) (accept-process-output ispell-process 5))
1642 (cond ((null ispell-filter) 1800 (cond ((null ispell-filter)
1643 (error "%s did not output version line" ispell-program-name)) 1801 (error "%s did not output version line" ispell-program-name))
1644 ((and 1802 ((and
1645 (stringp (car ispell-filter)) 1803 (stringp (car ispell-filter))
1646 (if (string-match "warning: " (car ispell-filter)) 1804 (if (string-match "warning: " (car ispell-filter))
1647 (progn 1805 (progn
1648 (accept-process-output ispell-process 5) ; 1st was warn msg. 1806 (if (not (string-match "18\\.[0-9]+\\.[0-9]+" emacs-version))
1807 (accept-process-output ispell-process 5) ; was warn msg.
1808 (accept-process-output ispell-process))
1649 (stringp (car ispell-filter))) 1809 (stringp (car ispell-filter)))
1650 (null (cdr ispell-filter))) 1810 (null (cdr ispell-filter)))
1651 (string-match "^@(#) " (car ispell-filter))) 1811 (string-match "^@(#) " (car ispell-filter)))
@@ -1715,7 +1875,7 @@ With prefix argument, set the default directory."
1715 (setq ispell-dictionary dict)) 1875 (setq ispell-dictionary dict))
1716 (if (null arg) ; set local dictionary 1876 (if (null arg) ; set local dictionary
1717 (setq ispell-local-dictionary dict))) 1877 (setq ispell-local-dictionary dict)))
1718 (error "Invalid Ispell dictionary: %s" dict)) 1878 (error "Undefined dictionary: %s" dict))
1719 (ispell-kill-ispell t) 1879 (ispell-kill-ispell t)
1720 (message "(Next %sIspell command will use %s dictionary)" 1880 (message "(Next %sIspell command will use %s dictionary)"
1721 (cond ((equal ispell-local-dictionary ispell-dictionary) 1881 (cond ((equal ispell-local-dictionary ispell-dictionary)
@@ -1746,225 +1906,60 @@ With prefix argument, set the default directory."
1746 (save-window-excursion 1906 (save-window-excursion
1747 (goto-char reg-start) 1907 (goto-char reg-start)
1748 (let ((transient-mark-mode nil) 1908 (let ((transient-mark-mode nil)
1749 ref-type) 1909 (case-fold-search case-fold-search)
1750 (while (and (not ispell-quit) (< (point) reg-end)) 1910 (skip-region-start (make-marker))
1751 (let ((start (point)) 1911 (skip-regexp (ispell-begin-skip-region-regexp))
1752 (offset-change 0) 1912 (skip-alist ispell-skip-region-alist)
1753 (end (save-excursion (end-of-line) (min (point) reg-end))) 1913 key)
1754 (ispell-casechars (ispell-get-casechars)) 1914 (if (eq ispell-parser 'tex)
1755 string) 1915 (setq case-fold-search nil
1756 (cond ; LOOK AT THIS LINE AND SKIP OR PROCESS 1916 skip-alist
1757 ((eolp) ; END OF LINE, just go to next line. 1917 (append (car ispell-tex-skip-alists)
1758 (forward-char 1)) 1918 (car (cdr ispell-tex-skip-alists))
1759 ((and (null ispell-check-comments) ; SKIPPING COMMENTS 1919 skip-alist)))
1760 comment-start ; skip comments that start on the line. 1920 (let (message-log-max)
1761 (search-forward comment-start end t)) ; or found here. 1921 (message "searching for regions to skip"))
1762 (if (= (- (point) start) (length comment-start)) 1922 (if (re-search-forward skip-regexp reg-end t)
1763 ;; comment starts the line. Skip entire line or region 1923 (progn
1764 (if (string= "" comment-end) ; skip to next line 1924 (setq key (buffer-substring-no-properties
1765 (beginning-of-line 2) ; or jump to comment end. 1925 (match-beginning 0) (match-end 0)))
1766 (search-forward comment-end reg-end 'limit)) 1926 (set-marker skip-region-start (- (point) (length key)))
1767 ;; Comment later in line. Check spelling before comment. 1927 (goto-char reg-start)))
1768 (let ((limit (- (point) (length comment-start)))) 1928 (let (message-log-max)
1769 (goto-char (1- limit)) 1929 (message "Continuing spelling check using %s dictionary..."
1770 (if (looking-at "\\\\") ; "quoted" comment, don't skip 1930 (or ispell-dictionary "default")))
1771 ;; quoted comment. Skip over comment-start 1931 (set-marker ispell-region-end reg-end)
1772 (if (= start (1- limit)) 1932 (while (and (not ispell-quit)
1773 (setq limit (+ limit (length comment-start))) 1933 (< (point) ispell-region-end))
1774 (setq limit (1- limit)))) 1934 ;; spell-check region with skipping
1775 (goto-char start) 1935 (if (and (marker-position skip-region-start)
1776 ;; Only check when "casechars" or math before comment 1936 (<= skip-region-start (point)))
1777 (if (or (re-search-forward ispell-casechars limit t) 1937 (progn
1778 (re-search-forward "[][()$]" limit t)) 1938 (ispell-skip-region key skip-alist) ; moves pt past region.
1779 (setq string 1939 (setq reg-start (point))
1780 (concat "^" (buffer-substring start limit) 1940 (if (and (< reg-start ispell-region-end)
1781 "\n") 1941 (re-search-forward skip-regexp
1782 offset-change (- offset-change ispell-offset))) 1942 ispell-region-end t))
1783 (goto-char limit)))) 1943 (progn
1784 ((looking-at "[---#@*+!%~^]") ; SKIP SPECIAL ISPELL CHARACTERS 1944 (setq key (buffer-substring-no-properties
1785 (forward-char 1)) 1945 (car (match-data))
1786 ((or (and ispell-skip-tib ; SKIP TIB REFERENCES OR SGML MARKUP 1946 (car (cdr (match-data)))))
1787 (re-search-forward ispell-tib-ref-beginning end t) 1947 (set-marker skip-region-start
1788 (setq ref-type 'tib)) 1948 (- (point) (length key)))
1789 (and ispell-skip-sgml 1949 (goto-char reg-start))
1790 (re-search-forward "[<&]" end t) 1950 (set-marker skip-region-start nil))))
1791 (setq ref-type 'sgml))) 1951 (setq reg-end (if (marker-position skip-region-start)
1792 (if (or (and (eq 'tib ref-type) ; tib tag is 2 chars. 1952 (min skip-region-start ispell-region-end)
1793 (= (- (point) 2) start)) 1953 (marker-position ispell-region-end)))
1794 (and (eq 'sgml ref-type) ; sgml skips 1 char. 1954 (let* ((start (point))
1795 (= (- (point) 1) start))) 1955 (end (save-excursion (end-of-line) (min (point) reg-end)))
1796 ;; Skip to end of reference, not necessarily on this line 1956 (string (ispell-get-line start end reg-end)))
1797 ;; Return an error if tib/sgml reference not found 1957 (setq end (point)) ; "end" tracks region retrieved.
1798 (if (or 1958 (if string ; there is something to spell check!
1799 (and 1959 (ispell-process-line string)) ; (special start end)
1800 (eq 'tib ref-type)
1801 (not
1802 (re-search-forward ispell-tib-ref-end reg-end t)))
1803 (and (eq 'sgml ref-type)
1804 (not (re-search-forward "[>;]" reg-end t))))
1805 (progn
1806 (ispell-pdict-save ispell-silently-savep)
1807 (ding)
1808 (message
1809 (concat
1810 "Open tib or SGML command. Fix buffer or set "
1811 (if (eq 'tib ref-type)
1812 "ispell-skip-tib"
1813 "ispell-skip-sgml")
1814 " to nil"))
1815 ;; keep cursor at error location
1816 (setq ispell-quit (- (point) 2))))
1817 ;; Check spelling between reference and start of the line.
1818 (let ((limit (- (point) (if (eq 'tib ref-type) 2 1))))
1819 (goto-char start)
1820 (if (or (re-search-forward ispell-casechars limit t)
1821 (re-search-forward "[][()$]" limit t))
1822 (setq string
1823 (concat "^" (buffer-substring start limit)
1824 "\n")
1825 offset-change (- offset-change ispell-offset)))
1826 (goto-char limit))))
1827 ((or (re-search-forward ispell-casechars end t) ; TEXT EXISTS
1828 (re-search-forward "[][()$]" end t)) ; or MATH COMMANDS
1829 (setq string (concat "^" (buffer-substring start end) "\n")
1830 offset-change (- offset-change ispell-offset))
1831 (goto-char end))
1832 (t (beginning-of-line 2))) ; EMPTY LINE, skip it.
1833
1834 (setq end (point)) ; "end" tracks end of region to check.
1835
1836 (if string ; there is something to spell!
1837 (let (poss)
1838 ;; send string to spell process and get input.
1839 (process-send-string ispell-process string)
1840 (while (progn
1841 (accept-process-output ispell-process)
1842 ;; Last item of output contains a blank line.
1843 (not (string= "" (car ispell-filter)))))
1844 ;; parse all inputs from the stream one word at a time.
1845 ;; Place in FIFO order and remove the blank item.
1846 (setq ispell-filter (nreverse (cdr ispell-filter)))
1847 (while (and (not ispell-quit) ispell-filter)
1848 (setq poss (ispell-parse-output (car ispell-filter)))
1849 (if (listp poss) ; spelling error occurred.
1850 (let* ((word-start
1851 (if (and enable-multibyte-characters
1852 (ispell-get-coding-system))
1853 ;; OFFSET returned by ispell
1854 ;; counts non-ASCII chars as
1855 ;; one, so just adding OFFSET
1856 ;; to START will cause an
1857 ;; error.
1858 (save-excursion
1859 (goto-char (+ start offset-change))
1860 (forward-char (car (cdr poss)))
1861 (point))
1862 (+ start offset-change
1863 (car (cdr poss)))))
1864 (word-end (+ word-start
1865 (length (car poss))))
1866 replace)
1867 (goto-char word-start)
1868 ;; Adjust the horizontal scroll & point
1869 (ispell-horiz-scroll)
1870 (goto-char word-end)
1871 (ispell-horiz-scroll)
1872 (goto-char word-start)
1873 (ispell-horiz-scroll)
1874 (if (/= word-end
1875 (progn
1876 (search-forward (car poss) word-end t)
1877 (point)))
1878 ;; This occurs due to filter pipe problems
1879 (error
1880 (concat "Ispell misalignment: word "
1881 "`%s' point %d; please retry")
1882 (car poss) word-start))
1883 (if (not (pos-visible-in-window-p))
1884 (sit-for 0))
1885 (if ispell-keep-choices-win
1886 (setq replace
1887 (ispell-command-loop
1888 (car (cdr (cdr poss)))
1889 (car (cdr (cdr (cdr poss))))
1890 (car poss) word-start word-end))
1891 (save-window-excursion
1892 (setq replace
1893 (ispell-command-loop
1894 (car (cdr (cdr poss)))
1895 (car (cdr (cdr (cdr poss))))
1896 (car poss) word-start word-end))))
1897 (cond
1898 ((and replace (listp replace))
1899 ;; REPLACEMENT WORD entered. Recheck line
1900 ;; starting with the replacement word.
1901 (setq ispell-filter nil
1902 string (buffer-substring word-start
1903 word-end))
1904 (let ((change (- (length (car replace))
1905 (length (car poss)))))
1906 ;; adjust regions
1907 (setq reg-end (+ reg-end change)
1908 offset-change (+ offset-change
1909 change)))
1910 (if (not (equal (car replace) (car poss)))
1911 (progn
1912 (delete-region word-start word-end)
1913 (insert (car replace))))
1914 ;; I only need to recheck typed-in replacements
1915 (if (not (eq 'query-replace
1916 (car (cdr replace))))
1917 (backward-char (length (car replace))))
1918 (setq end (point)) ; reposition for recheck
1919 ;; when second arg exists, query-replace, saving regions
1920 (if (car (cdr replace))
1921 (unwind-protect
1922 (save-window-excursion
1923 (set-marker
1924 ispell-query-replace-marker reg-end)
1925 ;; Assume case-replace &
1926 ;; case-fold-search correct?
1927 (query-replace string (car replace)
1928 t))
1929 (setq reg-end
1930 (marker-position
1931 ispell-query-replace-marker))
1932 (set-marker ispell-query-replace-marker
1933 nil))))
1934 ((or (null replace)
1935 (equal 0 replace)) ; ACCEPT/INSERT
1936 (if (equal 0 replace) ; BUFFER-LOCAL DICT ADD
1937 (setq reg-end
1938 (ispell-add-per-file-word-list
1939 (car poss) reg-end)))
1940 ;; This avoids pointing out the word that was
1941 ;; just accepted (via 'i' or 'a') if it follows
1942 ;; on the same line.
1943 ;; Redo check following the accepted word.
1944 (if (and ispell-pdict-modified-p
1945 (listp ispell-pdict-modified-p))
1946 ;; Word accepted. Recheck line.
1947 (setq ispell-pdict-modified-p ; update flag
1948 (car ispell-pdict-modified-p)
1949 ispell-filter nil ; discontinue check
1950 end word-start))) ; reposition loc.
1951 (replace ; STRING REPLACEMENT for this word.
1952 (delete-region word-start word-end)
1953 (insert replace)
1954 (let ((change (- (length replace)
1955 (length (car poss)))))
1956 (setq reg-end (+ reg-end change)
1957 offset-change (+ offset-change change)
1958 end (+ end change)))))
1959 (if (not ispell-quit)
1960 (let (message-log-max)
1961 (message "Continuing spelling check using %s dictionary..."
1962 (or ispell-dictionary "default"))))
1963 (sit-for 0)))
1964 ;; finished with line!
1965 (setq ispell-filter (cdr ispell-filter)))))
1966 (goto-char end))))) 1960 (goto-char end)))))
1967 (not ispell-quit)) 1961 ;;(not ispell-quit) ??? kss
1962 )
1968 ;; protected 1963 ;; protected
1969 (if (get-buffer ispell-choices-buffer) 1964 (if (get-buffer ispell-choices-buffer)
1970 (kill-buffer ispell-choices-buffer)) 1965 (kill-buffer ispell-choices-buffer))
@@ -1973,8 +1968,7 @@ With prefix argument, set the default directory."
1973 ;; preserve or clear the region for ispell-continue. 1968 ;; preserve or clear the region for ispell-continue.
1974 (if (not (numberp ispell-quit)) 1969 (if (not (numberp ispell-quit))
1975 (set-marker ispell-region-end nil) 1970 (set-marker ispell-region-end nil)
1976 ;; Enable ispell-continue. 1971 ;; Ispell-continue enabled - ispell-region-end is set.
1977 (set-marker ispell-region-end reg-end)
1978 (goto-char ispell-quit)) 1972 (goto-char ispell-quit))
1979 ;; Check for aborting 1973 ;; Check for aborting
1980 (if (and ispell-checking-message (numberp ispell-quit)) 1974 (if (and ispell-checking-message (numberp ispell-quit))
@@ -1988,6 +1982,274 @@ With prefix argument, set the default directory."
1988 (message "Spell-checking done")))) 1982 (message "Spell-checking done"))))
1989 1983
1990 1984
1985;;; Creates the regexp for skipping a region.
1986;;; Makes the skip-regxp local for tex buffers adding in the
1987;;; tex expressions to skip as well.
1988;;; Call AFTER ispell-buffer-local-parsing.
1989(defun ispell-begin-skip-region-regexp ()
1990 (let ((skip-regexp (ispell-begin-skip-region)))
1991 (if (and (null ispell-check-comments) comment-start)
1992 (setq skip-regexp (concat (regexp-quote comment-start) "\\|"
1993 skip-regexp)))
1994 (if (and (eq 'exclusive ispell-check-comments) comment-start)
1995 (setq skip-regexp (concat (if (string= "" comment-end) "^"
1996 (regexp-quote comment-end))
1997 "\\|" skip-regexp)))
1998 (if ispell-skip-tib
1999 (setq skip-regexp (concat ispell-tib-ref-beginning "\\|" skip-regexp)))
2000 (if ispell-skip-sgml
2001 (setq skip-regexp (concat "[<&]\\|" skip-regexp)))
2002 (if (eq ispell-parser 'tex)
2003 (setq skip-regexp (concat (ispell-begin-tex-skip-regexp) "\\|"
2004 skip-regexp)))
2005 skip-regexp))
2006
2007
2008;;; Regular expression of tex commands to skip.
2009;;; Generated from `ispell-tex-skip-alists'
2010(defun ispell-begin-tex-skip-regexp ()
2011 (concat
2012 (mapconcat (function (lambda (lst) (car lst)))
2013 (car ispell-tex-skip-alists)
2014 "\\|")
2015 "\\|"
2016 (mapconcat (function (lambda (lst)
2017 (concat "\\\\begin[ \t\n]*{[ \t\n]*"
2018 (car lst)
2019 "[ \t\n]*}")))
2020 (car (cdr ispell-tex-skip-alists))
2021 "\\|")))
2022
2023
2024;;; Regular expression of regions to skip for all buffers.
2025;;; Each selection should be a key of `ispell-skip-region-alist'
2026;;; otherwise, the current line is skipped.
2027(defun ispell-begin-skip-region ()
2028 (mapconcat (function (lambda (lst) (if (stringp (car lst)) (car lst)
2029 (eval (car lst)))))
2030 ispell-skip-region-alist
2031 "\\|"))
2032
2033
2034(defun ispell-tex-arg-end (&optional arg)
2035 (condition-case nil
2036 (progn
2037 (while (looking-at "[ \t\n]*\\[") (forward-sexp))
2038 (forward-sexp (or arg 1)))
2039 (error
2040 (message "error skipping s-expressions at point %d." (point))
2041 (beep)
2042 (sit-for 2))))
2043
2044
2045;;; Skips to region-end from point, or a single line.
2046;;; Places point at end of region skipped.
2047(defun ispell-skip-region (key alist)
2048 ;; move over key to begin checking.
2049 (forward-char (length key))
2050 (let ((start (point))
2051 alist-key null-skip)
2052 (cond
2053 ;; what about quoted comment, or comment inside strings?
2054 ((and (null ispell-check-comments) comment-start
2055 (string= key comment-start))
2056 (if (string= "" comment-end)
2057 (forward-line)
2058 (search-forward comment-end ispell-region-end t)))
2059 ((and (eq 'exclusive ispell-check-comments) comment-start
2060 (string= key comment-end))
2061 (search-forward comment-start ispell-region-end t))
2062 ((and ispell-skip-tib (string-match ispell-tib-ref-beginning key))
2063 (re-search-forward ispell-tib-ref-end ispell-region-end t))
2064 ((and ispell-skip-sgml (string-match "<" key))
2065 (search-forward ">" ispell-region-end t))
2066 ((and ispell-skip-sgml (string-match "&" key))
2067 (search-forward ";" ispell-region-end t))
2068 ;; markings from alist
2069 (t
2070 (while alist
2071 (setq alist-key (eval (car (car alist))))
2072 (if (string-match alist-key key)
2073 (progn
2074 (setq alist (cdr (car alist)))
2075 (cond
2076 ((null alist) (setq null-skip t)) ; done! Just skip key.
2077 ((not (consp alist))
2078 ;; Search past end of spell region to find this region end.
2079 (re-search-forward (eval alist) (point-max) t))
2080 ((consp alist)
2081 (if (stringp alist)
2082 (re-search-forward alist (point-max) t)
2083 (setq null-skip t) ; error handling in functions!
2084 (if (consp (cdr alist))
2085 (apply (car alist) (cdr alist))
2086 (funcall (car alist))))))
2087 (setq alist nil))
2088 (setq alist (cdr alist))))))
2089 (if (and (= start (point)) (null null-skip))
2090 (progn
2091 (message "Matching region end for `%s' point %d not found"
2092 key (point))
2093 (beep)
2094 (sit-for 2)))))
2095
2096
2097;;; Grab the next line of data.
2098;;; Returns a string with the line data
2099(defun ispell-get-line (start end reg-end)
2100 (let ((ispell-casechars (ispell-get-casechars))
2101 string)
2102 (cond ; LOOK AT THIS LINE AND SKIP OR PROCESS
2103 ((eolp) ; END OF LINE, just go to next line.
2104 (forward-line))
2105 ((looking-at "[---#@*+!%~^]") ; SKIP SPECIAL ISPELL CHARACTERS
2106 (forward-char 1))
2107 ((or (re-search-forward ispell-casechars end t) ; TEXT EXISTS
2108 (re-search-forward "[][()${}]" end t)) ; or MATH COMMANDS
2109 (setq string (concat "^" (buffer-substring-no-properties start end)
2110 "\n"))
2111 (goto-char end))
2112 (t (goto-char end))) ; EMPTY LINE, skip it.
2113 string))
2114
2115
2116(defun ispell-process-line (string)
2117 ;;(declare special start end)
2118 (let (poss)
2119 ;; send string to spell process and get input.
2120 (process-send-string ispell-process string)
2121 (while (progn
2122 (accept-process-output ispell-process)
2123 ;; Last item of output contains a blank line.
2124 (not (string= "" (car ispell-filter)))))
2125 ;; parse all inputs from the stream one word at a time.
2126 ;; Place in FIFO order and remove the blank item.
2127 (setq ispell-filter (nreverse (cdr ispell-filter)))
2128 (while (and (not ispell-quit) ispell-filter)
2129 (setq poss (ispell-parse-output (car ispell-filter)))
2130 (if (and poss (listp poss)) ; spelling error occurred.
2131 ;; Whenever we have misspellings, we can change
2132 ;; the buffer. Keep boundaries as markers.
2133 ;; Markers can move with highlighting! This destroys
2134 ;; end of region markers line-end and ispell-region-end
2135 (let ((word-start
2136 (copy-marker
2137 (if (and (boundp 'enable-multibyte-characters)
2138 enable-multibyte-characters
2139 (ispell-get-coding-system))
2140 ;; skip over multibyte characters correctly
2141 (save-excursion
2142 (goto-char (+ start ispell-offset))
2143 (forward-char (car (cdr poss)))
2144 (point))
2145 (+ start ispell-offset (car (cdr poss))))))
2146 (word-len (length (car poss)))
2147 (line-end (copy-marker end))
2148 (line-start (copy-marker start))
2149 recheck-region replace)
2150 (goto-char word-start)
2151 ;; Adjust the horizontal scroll & point
2152 (ispell-horiz-scroll)
2153 (goto-char (+ word-len word-start))
2154 (ispell-horiz-scroll)
2155 (goto-char word-start)
2156 (ispell-horiz-scroll)
2157 (if (/= (+ word-len (point))
2158 (progn
2159 (search-forward (car poss) (+ word-len (point)) t)
2160 (point)))
2161 ;; This occurs due to filter pipe problems
2162 (error (concat "Ispell misalignment: word "
2163 "`%s' point %d; probably incompatible versions")
2164 (car poss) (marker-position word-start)))
2165
2166 ;; ispell-cmd-loop can go recursive & change buffer
2167 (if ispell-keep-choices-win
2168 (setq replace (ispell-command-loop
2169 (car (cdr (cdr poss)))
2170 (car (cdr (cdr (cdr poss))))
2171 (car poss) (marker-position word-start)
2172 (+ word-len (marker-position word-start))))
2173 (save-window-excursion
2174 (setq replace (ispell-command-loop
2175 (car (cdr (cdr poss)))
2176 (car (cdr (cdr (cdr poss))))
2177 (car poss) (marker-position word-start)
2178 (+ word-len (marker-position word-start))))))
2179
2180 ;; Recheck when recursive edit changes misspelled word
2181 (goto-char word-start)
2182 (if (not (string-equal (buffer-substring-no-properties
2183 (point) (+ word-len (point)))
2184 (car poss)))
2185 (progn
2186 (set-marker line-end (point))
2187 (setq ispell-filter nil
2188 recheck-region t)))
2189
2190 (cond
2191 ((and replace (listp replace))
2192 ;; REPLACEMENT WORD
2193 ;; Recheck line starting with the replacement word.
2194 (setq ispell-filter nil
2195 recheck-region t)
2196 (delete-region (point) (+ word-len (point)))
2197 (insert (car replace))
2198 ;; Only typed-in replacements need to be re-checked.
2199 (if (not (eq 'query-replace (car (cdr replace))))
2200 (backward-char (length (car replace))))
2201 (set-marker line-end (point)) ; continue checking from here.
2202 (if (car (cdr replace))
2203 (unwind-protect
2204 (save-window-excursion
2205 (delete-other-windows) ; to correctly show help.
2206 ;; Assume case-replace &
2207 ;; case-fold-search correct?
2208 (query-replace (car poss) (car replace) t))
2209 (goto-char word-start))))
2210 ((or (null replace)
2211 (equal 0 replace)) ; ACCEPT/INSERT
2212 (if (equal 0 replace) ; BUFFER-LOCAL DICT ADD
2213 (ispell-add-per-file-word-list (car poss)))
2214 ;; This avoids pointing out the word that was
2215 ;; just accepted (via 'i' or 'a') if it follows
2216 ;; on the same line.
2217 ;; Redo check following the accepted word.
2218 (if (and ispell-pdict-modified-p
2219 (listp ispell-pdict-modified-p))
2220 ;; Word accepted. Recheck line.
2221 (progn
2222 (setq ispell-pdict-modified-p ;update flag
2223 (car ispell-pdict-modified-p)
2224 ispell-filter nil
2225 recheck-region t)
2226 (set-marker line-end (marker-position word-start)))))
2227 (replace ; STRING REPLACEMENT for this word.
2228 (delete-region (point) (+ word-len (point)))
2229 (insert replace)
2230 (set-marker line-start (+ line-start
2231 (- (length replace)
2232 (length (car poss)))))))
2233 (if (not ispell-quit)
2234 (let (message-log-max)
2235 (message "Continuing spelling check using %s dictionary..."
2236 (or ispell-dictionary "default"))))
2237 (sit-for 0)
2238 (setq start (marker-position line-start)
2239 end (marker-position line-end))
2240 ;; Adjust markers when end of region lost from highlighting.
2241 (if (and (not recheck-region) (< end (+ word-start word-len)))
2242 (setq end (+ word-start word-len)))
2243 (if (= word-start ispell-region-end)
2244 (set-marker ispell-region-end (+ word-start word-len)))
2245 ;; going out of scope - unneeded
2246 (set-marker line-start nil)
2247 (set-marker word-start nil)
2248 (set-marker line-end nil)))
2249 ;; finished with misspelling!
2250 (setq ispell-filter (cdr ispell-filter)))))
2251
2252
1991;;;###autoload 2253;;;###autoload
1992(defun ispell-comments-and-strings () 2254(defun ispell-comments-and-strings ()
1993 "Check comments and strings in the current buffer for spelling errors." 2255 "Check comments and strings in the current buffer for spelling errors."
@@ -2018,13 +2280,16 @@ With prefix argument, set the default directory."
2018;;;###autoload 2280;;;###autoload
2019(defun ispell-continue () 2281(defun ispell-continue ()
2020 (interactive) 2282 (interactive)
2021 "Continue a spelling session after making some changes." 2283 "Continue a halted spelling session beginning with the current word."
2022 (if (not (marker-position ispell-region-end)) 2284 (if (not (marker-position ispell-region-end))
2023 (message "No session to continue. Use 'X' command when checking!") 2285 (message "No session to continue. Use 'X' command when checking!")
2024 (if (not (equal (marker-buffer ispell-region-end) (current-buffer))) 2286 (if (not (equal (marker-buffer ispell-region-end) (current-buffer)))
2025 (message "Must continue ispell from buffer %s" 2287 (message "Must continue ispell from buffer %s"
2026 (buffer-name (marker-buffer ispell-region-end))) 2288 (buffer-name (marker-buffer ispell-region-end)))
2027 (ispell-region (point) (marker-position ispell-region-end))))) 2289 (ispell-region
2290 ;; find beginning of current word:
2291 (car (cdr (ispell-get-word t)))
2292 (marker-position ispell-region-end)))))
2028 2293
2029 2294
2030;;; Horizontal scrolling 2295;;; Horizontal scrolling
@@ -2059,7 +2324,9 @@ Standard ispell choices are then available."
2059 word (car word) 2324 word (car word)
2060 possibilities 2325 possibilities
2061 (or (string= word "") ; Will give you every word 2326 (or (string= word "") ; Will give you every word
2062 (lookup-words (concat (if interior-frag "*") word "*") 2327 (lookup-words (concat (and interior-frag "*") word
2328 (if (or interior-frag (null ispell-look-p))
2329 "*"))
2063 ispell-complete-word-dict))) 2330 ispell-complete-word-dict)))
2064 (cond ((eq possibilities t) 2331 (cond ((eq possibilities t)
2065 (message "No word to complete")) 2332 (message "No word to complete"))
@@ -2134,7 +2401,10 @@ Standard ispell choices are then available."
2134With prefix arg, turn Ispell minor mode on iff arg is positive. 2401With prefix arg, turn Ispell minor mode on iff arg is positive.
2135 2402
2136In Ispell minor mode, pressing SPC or RET 2403In Ispell minor mode, pressing SPC or RET
2137warns you if the previous word is incorrectly spelled." 2404warns you if the previous word is incorrectly spelled.
2405
2406All the buffer-local variables and dictionaries are ignored -- to read
2407them into the running ispell process, type \\[ispell-word] SPC."
2138 (interactive "P") 2408 (interactive "P")
2139 (setq ispell-minor-mode 2409 (setq ispell-minor-mode
2140 (not (or (and (null arg) ispell-minor-mode) 2410 (not (or (and (null arg) ispell-minor-mode)
@@ -2142,14 +2412,19 @@ warns you if the previous word is incorrectly spelled."
2142 (force-mode-line-update)) 2412 (force-mode-line-update))
2143 2413
2144(defun ispell-minor-check () 2414(defun ispell-minor-check ()
2145 ;; Check previous word then continue with the normal binding of this key. 2415 "Check previous word then continue with the normal binding of this key.
2416Don't check previous word when character before point is a space or newline.
2417Don't read buffer-local settings or word lists."
2146 (interactive "*") 2418 (interactive "*")
2147 (let ((ispell-minor-mode nil) 2419 (let ((ispell-minor-mode nil)
2148 (ispell-check-only t)) 2420 (ispell-check-only t)
2149 (save-excursion 2421 (last-char (char-after (1- (point)))))
2150 (save-restriction 2422 (if (or (eq last-char ?\ ) (eq last-char ?\n))
2151 (narrow-to-region (point-min) (point)) 2423 nil
2152 (ispell-word nil t))) 2424 (save-window-excursion
2425 (save-restriction
2426 (narrow-to-region (save-excursion (forward-line -1) (point)) (point))
2427 (ispell-word nil t))))
2153 (call-interactively (key-binding (this-command-keys))))) 2428 (call-interactively (key-binding (this-command-keys)))))
2154 2429
2155 2430
@@ -2162,6 +2437,8 @@ warns you if the previous word is incorrectly spelled."
2162(defvar ispell-message-text-end 2437(defvar ispell-message-text-end
2163 (mapconcat (function identity) 2438 (mapconcat (function identity)
2164 '( 2439 '(
2440 ;; Don't spell check signatures
2441 "^-- $"
2165 ;; Matches postscript files. 2442 ;; Matches postscript files.
2166 "^%!PS-Adobe-[123].0" 2443 "^%!PS-Adobe-[123].0"
2167 ;; Matches uuencoded text 2444 ;; Matches uuencoded text
@@ -2169,44 +2446,19 @@ warns you if the previous word is incorrectly spelled."
2169 ;; Matches shell files (esp. auto-decoding) 2446 ;; Matches shell files (esp. auto-decoding)
2170 "^#! /bin/[ck]?sh" 2447 "^#! /bin/[ck]?sh"
2171 ;; Matches context difference listing 2448 ;; Matches context difference listing
2172 "\\(diff -c .*\\)?\n\\*\\*\\* .*\n--- .*\n\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*" 2449 "\\(\\(^cd .*\n\\)?diff -c .*\\)?\n\\*\\*\\* .*\n--- .*\n\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*"
2173 ;; Matches reporter.el bug report 2450 ;; Matches unidiff difference listing
2174 "^current state:\n==============\n" 2451 "\\(diff -u .*\\)?\n--- .*\n\\+\\+\\+ .*\n@@ [-+][0-9]+,[0-9]+ [-+][0-9]+,[0-9]+ @@\n"
2175 ;; Matches "----------------- cut here" 2452 ;; Matches reporter.el bug report
2176 ;; and "------- Start of forwarded message", 2453 "^current state:\n==============\n"
2177 ;; or either one with "- " in front. 2454 ;; Matches commonly used "cut" boundaries
2178 "^\\(- \\)?[-=_]+\\s ?\\(cut here\\|\\(Start of \\)?forwarded message\\)") 2455 "^\\(- \\)?[-=_]+\\s ?\\(cut here\\|Environment Follows\\)")
2179 "\\|") 2456 "\\|")
2180 "*End of text which will be checked in ispell-message. 2457 "*End of text which will be checked in ispell-message.
2181If it is a string, limit at first occurrence of that regular expression. 2458If it is a string, limit at first occurrence of that regular expression.
2182Otherwise, it must be a function which is called to get the limit.") 2459Otherwise, it must be a function which is called to get the limit.")
2183 2460
2184 2461
2185(defvar ispell-message-start-skip
2186 (mapconcat (function identity)
2187 '(
2188 ;; Matches forwarded messages
2189 "^---* Forwarded Message"
2190 ;; Matches PGP Public Key block
2191 "^---*BEGIN PGP [A-Z ]*--*"
2192 )
2193 "\\|")
2194 "Spelling is skipped inside these start/end groups by ispell-message.
2195Assumed that blocks are not mutually inclusive.")
2196
2197
2198(defvar ispell-message-end-skip
2199 (mapconcat (function identity)
2200 '(
2201 ;; Matches forwarded messages
2202 "^--- End of Forwarded Message"
2203 ;; Matches PGP Public Key block
2204 "^---*END PGP [A-Z ]*--*"
2205 )
2206 "\\|")
2207 "Spelling is skipped inside these start/end groups by ispell-message.
2208Assumed that blocks are not mutually inclusive.")
2209
2210 2462
2211;;;###autoload 2463;;;###autoload
2212(defun ispell-message () 2464(defun ispell-message ()
@@ -2220,7 +2472,8 @@ The `X' command aborts the message send so that you can edit the buffer.
2220 2472
2221To spell-check whenever a message is sent, include the appropriate lines 2473To spell-check whenever a message is sent, include the appropriate lines
2222in your .emacs file: 2474in your .emacs file:
2223 (add-hook 'message-send-hook 'ispell-message) 2475 (add-hook 'message-send-hook 'ispell-message) ;; GNUS 5
2476 (add-hook 'news-inews-hook 'ispell-message) ;; GNUS 4
2224 (add-hook 'mail-send-hook 'ispell-message) 2477 (add-hook 'mail-send-hook 'ispell-message)
2225 (add-hook 'mh-before-send-letter-hook 'ispell-message) 2478 (add-hook 'mh-before-send-letter-hook 'ispell-message)
2226 2479
@@ -2230,13 +2483,18 @@ You can bind this to the key C-c i in GNUS or mail by adding to
2230 (interactive) 2483 (interactive)
2231 (save-excursion 2484 (save-excursion
2232 (goto-char (point-min)) 2485 (goto-char (point-min))
2233 (let* ((internal-messagep (save-excursion 2486 (let* (
2234 (re-search-forward 2487 ;; Nil when message came from outside (eg calling emacs as editor)
2235 (concat "^" 2488 ;; Non-nil marker of end of headers.
2236 (regexp-quote mail-header-separator) 2489 (internal-messagep
2237 "$") 2490 (re-search-forward
2238 nil t))) 2491 (concat "^" (regexp-quote mail-header-separator) "$") nil t))
2239 (limit (copy-marker 2492 (end-of-headers ; Start of body.
2493 (copy-marker
2494 (or internal-messagep
2495 (re-search-forward "^$" nil t)
2496 (point-min))))
2497 (limit (copy-marker ; End of region we will spell check.
2240 (cond 2498 (cond
2241 ((not ispell-message-text-end) (point-max)) 2499 ((not ispell-message-text-end) (point-max))
2242 ((char-or-string-p ispell-message-text-end) 2500 ((char-or-string-p ispell-message-text-end)
@@ -2244,7 +2502,11 @@ You can bind this to the key C-c i in GNUS or mail by adding to
2244 (match-beginning 0) 2502 (match-beginning 0)
2245 (point-max))) 2503 (point-max)))
2246 (t (min (point-max) (funcall ispell-message-text-end)))))) 2504 (t (min (point-max) (funcall ispell-message-text-end))))))
2247 (cite-regexp ;Prefix of inserted text 2505 (default-prefix ; Vanilla cite prefix (just used for cite-regexp)
2506 (if (and (boundp 'mail-yank-prefix) mail-yank-prefix)
2507 (ispell-non-empty-string mail-yank-prefix)
2508 " \\|\t"))
2509 (cite-regexp ;Prefix of quoted text
2248 (cond 2510 (cond
2249 ((featurep 'supercite) ; sc 3.0 2511 ((featurep 'supercite) ; sc 3.0
2250 (concat "\\(" (sc-cite-regexp) "\\)" "\\|" 2512 (concat "\\(" (sc-cite-regexp) "\\)" "\\|"
@@ -2252,86 +2514,61 @@ You can bind this to the key C-c i in GNUS or mail by adding to
2252 ((featurep 'sc) ; sc 2.3 2514 ((featurep 'sc) ; sc 2.3
2253 (concat "\\(" sc-cite-regexp "\\)" "\\|" 2515 (concat "\\(" sc-cite-regexp "\\)" "\\|"
2254 (ispell-non-empty-string sc-reference-tag-string))) 2516 (ispell-non-empty-string sc-reference-tag-string)))
2255 ((equal major-mode 'news-reply-mode) ;GNUS 4 & below 2517 ((or (equal major-mode 'news-reply-mode) ;GNUS 4 & below
2518 (equal major-mode 'message-mode)) ;GNUS 5
2256 (concat "In article <" "\\|" 2519 (concat "In article <" "\\|"
2257 (if mail-yank-prefix 2520 "[^,;&+=]+ <[^,;&+=]+> writes:" "\\|"
2258 (ispell-non-empty-string mail-yank-prefix) 2521 default-prefix))
2259 "^ \\|^\t")))
2260 ((equal major-mode 'message-mode) ;GNUS 5
2261 (concat ".*@.* writes:$" "\\|"
2262 (if mail-yank-prefix
2263 (ispell-non-empty-string mail-yank-prefix)
2264 "^ \\|^\t")))
2265 ((equal major-mode 'mh-letter-mode) ; mh mail message 2522 ((equal major-mode 'mh-letter-mode) ; mh mail message
2266 (ispell-non-empty-string mh-ins-buf-prefix)) 2523 (ispell-non-empty-string mh-ins-buf-prefix))
2267 ((not internal-messagep) ; Assume n sent us this message. 2524 ((not internal-messagep) ; Assume nn sent us this message.
2268 (concat "In [a-zA-Z.]+ you write:" "\\|" 2525 (concat "In [a-zA-Z.]+ you write:" "\\|"
2269 "In <[^,;&+=]+> [^,;&+=]+ writes:" "\\|" 2526 "In <[^,;&+=]+> [^,;&+=]+ writes:" "\\|"
2270 " *> *")) 2527 " *> *"))
2271 ((boundp 'vm-included-text-prefix) ; VM mail message 2528 ((boundp 'vm-included-text-prefix) ; VM mail message
2272 (concat "[^,;&+=]+ writes:" "\\|" 2529 (concat "[^,;&+=]+ writes:" "\\|"
2273 (ispell-non-empty-string vm-included-text-prefix))) 2530 (ispell-non-empty-string vm-included-text-prefix)))
2274 (mail-yank-prefix ; vanilla mail message. 2531 (t default-prefix)))
2275 (ispell-non-empty-string mail-yank-prefix)) 2532 (ispell-skip-region-alist
2276 (t "^ \\|^\t"))) 2533 (cons (list (concat "^\\(" cite-regexp "\\)")
2277 (cite-regexp-start (concat "^[ \t]*$\\|" cite-regexp)) 2534 (function forward-line))
2278 (cite-regexp-end (concat "^\\(" cite-regexp "\\)")) 2535 ispell-skip-region-alist))
2279 (old-case-fold-search case-fold-search) 2536 (old-case-fold-search case-fold-search)
2280 (case-fold-search t) 2537 (case-fold-search t)
2538 (dictionary-alist ispell-message-dictionary-alist)
2281 (ispell-checking-message t)) 2539 (ispell-checking-message t))
2282 (goto-char (point-min)) 2540
2283 ;; Skip header fields except Subject: without Re:'s 2541 ;; Select dictionary for message
2284 ;;(search-forward mail-header-separator nil t) 2542 (or (local-variable-p 'ispell-local-dictionary (current-buffer))
2285 (while (if internal-messagep 2543 (while dictionary-alist
2286 (< (point) internal-messagep) 2544 (goto-char (point-min))
2287 (and (looking-at "[a-zA-Z---]+:\\|\t\\| ") 2545 (if (re-search-forward (car (car dictionary-alist))
2288 (not (eobp)))) 2546 end-of-headers t)
2289 (if (looking-at "Subject: *") ; Spell check new subject fields 2547 (setq ispell-local-dictionary (cdr (car dictionary-alist))
2290 (progn 2548 dictionary-alist nil)
2291 (goto-char (match-end 0)) 2549 (setq dictionary-alist (cdr dictionary-alist)))))
2292 (if (and (not (looking-at ".*Re\\>")) 2550
2293 (not (looking-at "\\["))) 2551 (unwind-protect
2294 (let ((case-fold-search old-case-fold-search)) 2552 (progn
2295 (ispell-region (point) 2553 ;; Spell check any original Subject:
2296 (progn 2554 (goto-char (point-min))
2297 (end-of-line) 2555 (if (re-search-forward "^Subject: *" end-of-headers t)
2298 (while (looking-at "\n[ \t]") 2556 (progn
2299 (end-of-line 2)) 2557 (goto-char (match-end 0))
2300 (point))))))) 2558 (if (and (not (looking-at ".*Re\\>"))
2301 (forward-line 1)) 2559 (not (looking-at "\\[")))
2302 (setq case-fold-search nil) 2560 (let ((case-fold-search old-case-fold-search))
2303 ;; Skip mail header, particularly for non-english languages. 2561 (ispell-region (point)
2304 (if (looking-at (concat (regexp-quote mail-header-separator) "$")) 2562 (progn ;Tab-initiated continuation lns.
2305 (forward-line 1)) 2563 (end-of-line)
2306 (while (< (point) limit) 2564 (while (looking-at "\n[ \t]")
2307 ;; Skip across text cited from other messages. 2565 (end-of-line 2))
2308 (while (and (looking-at cite-regexp-start) 2566 (point)))))))
2309 (< (point) limit) 2567 (goto-char end-of-headers)
2310 (zerop (forward-line 1)))) 2568 (forward-line 1)
2311 2569 (ispell-region (point) limit))
2312 (if (< (point) limit) 2570 (set-marker end-of-headers nil)
2313 (let* ((start (point)) 2571 (set-marker limit nil)))))
2314 ;; Check the next batch of lines that *aren't* cited.
2315 (end-c (and (re-search-forward cite-regexp-end limit 'end)
2316 (match-beginning 0)))
2317 ;; Skip a block of included text.
2318 (end-fwd (and (goto-char start)
2319 (re-search-forward ispell-message-start-skip
2320 limit 'end)
2321 (progn (beginning-of-line)
2322 (point))))
2323 (end (or (and end-c end-fwd (min end-c end-fwd))
2324 end-c end-fwd
2325 ;; default to limit of text.
2326 (marker-position limit))))
2327 (goto-char start)
2328 (ispell-region start end)
2329 (if (and end-fwd (= end end-fwd))
2330 (progn
2331 (goto-char end)
2332 (re-search-forward ispell-message-end-skip limit 'end))
2333 (goto-char end)))))
2334 (set-marker limit nil))))
2335 2572
2336 2573
2337(defun ispell-non-empty-string (string) 2574(defun ispell-non-empty-string (string)
@@ -2346,7 +2583,7 @@ You can bind this to the key C-c i in GNUS or mail by adding to
2346 2583
2347 2584
2348(defun ispell-accept-buffer-local-defs () 2585(defun ispell-accept-buffer-local-defs ()
2349 "Load all buffer-local information, restarting ispell when necessary." 2586 "Load all buffer-local information, restarting Ispell when necessary."
2350 (ispell-buffer-local-dict) ; May kill ispell-process. 2587 (ispell-buffer-local-dict) ; May kill ispell-process.
2351 (ispell-buffer-local-words) ; Will initialize ispell-process. 2588 (ispell-buffer-local-words) ; Will initialize ispell-process.
2352 (ispell-buffer-local-parsing)) 2589 (ispell-buffer-local-parsing))
@@ -2355,46 +2592,55 @@ You can bind this to the key C-c i in GNUS or mail by adding to
2355(defun ispell-buffer-local-parsing () 2592(defun ispell-buffer-local-parsing ()
2356 "Place Ispell into parsing mode for this buffer. 2593 "Place Ispell into parsing mode for this buffer.
2357Overrides the default parsing mode. 2594Overrides the default parsing mode.
2358Includes latex/nroff modes and extended character mode." 2595Includes Latex/Nroff modes and extended character mode."
2359 ;; (ispell-init-process) must already be called. 2596 ;; (ispell-init-process) must already be called.
2360 (process-send-string ispell-process "!\n") ; Put process in terse mode. 2597 (process-send-string ispell-process "!\n") ; Put process in terse mode.
2361 ;; We assume all major modes with "tex-mode" in them should use latex parsing 2598 ;; We assume all major modes with "tex-mode" in them should use latex parsing
2362 (if (or (and (eq ispell-parser 'use-mode-name) 2599 (if (or (and (eq ispell-parser 'use-mode-name)
2363 (string-match "[Tt][Ee][Xx]-mode" (symbol-name major-mode))) 2600 (string-match "[Tt][Ee][Xx]-mode" (symbol-name major-mode)))
2364 (eq ispell-parser 'tex)) 2601 (eq ispell-parser 'tex))
2365 (process-send-string ispell-process "+\n") ; set ispell mode to tex 2602 (progn
2603 (process-send-string ispell-process "+\n") ; set ispell mode to tex
2604 (if (not (eq ispell-parser 'tex))
2605 (set (make-local-variable 'ispell-parser) 'tex)))
2366 (process-send-string ispell-process "-\n")) ; set mode to normal (nroff) 2606 (process-send-string ispell-process "-\n")) ; set mode to normal (nroff)
2367 ;; Hard-wire test for SGML & HTML mode. 2607 ;; If needed, test for SGML & HTML modes and set a buffer local nil/t value.
2368 (setq ispell-skip-sgml (memq major-mode '(sgml-mode html-mode))) 2608 (if (and ispell-skip-sgml (not (eq ispell-skip-sgml t)))
2609 (set (make-local-variable 'ispell-skip-sgml)
2610 (not (null (let ((case-fold-search t))
2611 (string-match "sgml\\|html"
2612 (symbol-name major-mode)))))))
2369 ;; Set default extended character mode for given buffer, if any. 2613 ;; Set default extended character mode for given buffer, if any.
2370 (let ((extended-char-mode (ispell-get-extended-character-mode))) 2614 (let ((extended-char-mode (ispell-get-extended-character-mode)))
2371 (if extended-char-mode 2615 (if extended-char-mode
2372 (process-send-string ispell-process (concat extended-char-mode "\n")))) 2616 (process-send-string ispell-process (concat extended-char-mode "\n"))))
2373 ;; Set buffer-local parsing mode and extended character mode, if specified. 2617 ;; Set buffer-local parsing mode and extended character mode, if specified.
2374 (save-excursion 2618 (save-excursion
2375 (goto-char (point-min)) 2619 (goto-char (point-max))
2376 ;; Uses last valid definition 2620 ;; Uses last occurrence of ispell-parsing-keyword
2377 (while (search-forward ispell-parsing-keyword nil t) 2621 (if (search-backward ispell-parsing-keyword nil t)
2378 (let ((end (save-excursion (end-of-line) (point))) 2622 (let ((end (save-excursion (end-of-line) (point)))
2379 (case-fold-search t) 2623 (case-fold-search t)
2380 string) 2624 string)
2381 (while (re-search-forward " *\\([^ \"]+\\)" end t) 2625 (search-forward ispell-parsing-keyword)
2382 ;; space separated definitions. 2626 (while (re-search-forward " *\\([^ \"]+\\)" end t)
2383 (setq string (buffer-substring (match-beginning 1) (match-end 1))) 2627 ;; space separated definitions.
2384 (cond ((string-match "latex-mode" string) 2628 (setq string (buffer-substring-no-properties (match-beginning 1)
2385 (process-send-string ispell-process "+\n~tex\n")) 2629 (match-end 1)))
2386 ((string-match "nroff-mode" string) 2630 (cond ((string-match "latex-mode" string)
2387 (process-send-string ispell-process "-\n~nroff")) 2631 (process-send-string ispell-process "+\n~tex\n"))
2388 ((string-match "~" string) ; Set extended character mode. 2632 ((string-match "nroff-mode" string)
2389 (process-send-string ispell-process (concat string "\n"))) 2633 (process-send-string ispell-process "-\n~nroff"))
2390 (t (message "Invalid Ispell Parsing argument!") 2634 ((string-match "~" string) ; Set extended character mode.
2391 (sit-for 2)))))))) 2635 (process-send-string ispell-process (concat string "\n")))
2636 (t (message "Invalid Ispell Parsing argument!")
2637 (sit-for 2))))))))
2392 2638
2393 2639
2394;;; Can kill the current ispell process 2640;;; Can kill the current ispell process
2395 2641
2396(defun ispell-buffer-local-dict () 2642(defun ispell-buffer-local-dict ()
2397 "Initializes local dictionary. 2643 "Initializes local dictionary and local personal dictionary.
2398When a dictionary is defined in the buffer (see variable 2644When a dictionary is defined in the buffer (see variable
2399`ispell-dictionary-keyword'), it will override the local setting 2645`ispell-dictionary-keyword'), it will override the local setting
2400from \\[ispell-change-dictionary]. 2646from \\[ispell-change-dictionary].
@@ -2403,20 +2649,25 @@ Both should not be used to define a buffer-local dictionary."
2403 (goto-char (point-min)) 2649 (goto-char (point-min))
2404 (let (end) 2650 (let (end)
2405 ;; Override the local variable definition. 2651 ;; Override the local variable definition.
2406 ;; Uses last valid definition. 2652 ;; Uses last occurrence of ispell-dictionary-keyword.
2407 (while (search-forward ispell-dictionary-keyword nil t) 2653 (goto-char (point-max))
2408 (setq end (save-excursion (end-of-line) (point))) 2654 (if (search-backward ispell-dictionary-keyword nil t)
2409 (if (re-search-forward " *\\([^ \"]+\\)" end t) 2655 (progn
2410 (setq ispell-local-dictionary 2656 (search-forward ispell-dictionary-keyword)
2411 (buffer-substring-no-properties (match-beginning 1) 2657 (setq end (save-excursion (end-of-line) (point)))
2412 (match-end 1))))) 2658 (if (re-search-forward " *\\([^ \"]+\\)" end t)
2413 (goto-char (point-min)) 2659 (setq ispell-local-dictionary
2414 (while (search-forward ispell-pdict-keyword nil t) 2660 (buffer-substring-no-properties (match-beginning 1)
2415 (setq end (save-excursion (end-of-line) (point))) 2661 (match-end 1))))))
2416 (if (re-search-forward " *\\([^ \"]+\\)" end t) 2662 (goto-char (point-max))
2417 (setq ispell-local-pdict 2663 (if (search-backward ispell-pdict-keyword nil t)
2418 (buffer-substring-no-properties (match-beginning 1) 2664 (progn
2419 (match-end 1))))))) 2665 (search-forward ispell-pdict-keyword)
2666 (setq end (save-excursion (end-of-line) (point)))
2667 (if (re-search-forward " *\\([^ \"]+\\)" end t)
2668 (setq ispell-local-pdict
2669 (buffer-substring-no-properties (match-beginning 1)
2670 (match-end 1))))))))
2420 ;; Reload if new personal dictionary defined. 2671 ;; Reload if new personal dictionary defined.
2421 (if (and ispell-local-pdict 2672 (if (and ispell-local-pdict
2422 (not (equal ispell-local-pdict ispell-personal-dictionary))) 2673 (not (equal ispell-local-pdict ispell-personal-dictionary)))
@@ -2443,22 +2694,27 @@ Both should not be used to define a buffer-local dictionary."
2443 (or ispell-buffer-local-name 2694 (or ispell-buffer-local-name
2444 (setq ispell-buffer-local-name (buffer-name))) 2695 (setq ispell-buffer-local-name (buffer-name)))
2445 (let ((end (save-excursion (end-of-line) (point))) 2696 (let ((end (save-excursion (end-of-line) (point)))
2697 (ispell-casechars (ispell-get-casechars))
2446 string) 2698 string)
2447 ;; buffer-local words separated by a space, and can contain 2699 ;; buffer-local words separated by a space, and can contain
2448 ;; any character other than a space. 2700 ;; any character other than a space. Not rigorous enough.
2449 (while (re-search-forward " *\\([^ ]+\\)" end t) 2701 (while (re-search-forward " *\\([^ ]+\\)" end t)
2450 (setq string (buffer-substring (match-beginning 1) (match-end 1))) 2702 (setq string (buffer-substring-no-properties (match-beginning 1)
2451 (process-send-string ispell-process (concat "@" string "\n"))))))) 2703 (match-end 1)))
2704 ;; This can fail when string contains a word with illegal chars.
2705 ;; Error handling needs to be added between ispell and emacs.
2706 (if (and (< 1 (length string))
2707 (equal 0 (string-match ispell-casechars string)))
2708 (process-send-string ispell-process
2709 (concat "@" string "\n"))))))))
2452 2710
2453 2711
2454;;; returns optionally adjusted region-end-point. 2712;;; returns optionally adjusted region-end-point.
2455 2713
2456(defun ispell-add-per-file-word-list (word &optional reg-end) 2714(defun ispell-add-per-file-word-list (word)
2457 "Adds new word to the per-file word list." 2715 "Adds new word to the per-file word list."
2458 (or ispell-buffer-local-name 2716 (or ispell-buffer-local-name
2459 (setq ispell-buffer-local-name (buffer-name))) 2717 (setq ispell-buffer-local-name (buffer-name)))
2460 (if (null reg-end)
2461 (setq reg-end 0))
2462 (save-excursion 2718 (save-excursion
2463 (goto-char (point-min)) 2719 (goto-char (point-min))
2464 (let (case-fold-search line-okay search done string) 2720 (let (case-fold-search line-okay search done string)
@@ -2476,22 +2732,16 @@ Both should not be used to define a buffer-local dictionary."
2476 (open-line 1) 2732 (open-line 1)
2477 (setq string (concat comment-start " " 2733 (setq string (concat comment-start " "
2478 ispell-words-keyword)) 2734 ispell-words-keyword))
2479 ;; in case the keyword is in the middle of the file....
2480 (if (> reg-end (point))
2481 (setq reg-end (+ reg-end (length string))))
2482 (insert string) 2735 (insert string)
2483 (if (and comment-end (not (equal "" comment-end))) 2736 (if (and comment-end (not (equal "" comment-end)))
2484 (save-excursion 2737 (save-excursion
2485 (open-line 1) 2738 (open-line 1)
2486 (forward-line 1) 2739 (forward-line 1)
2487 (insert comment-end))))) 2740 (insert comment-end)))))
2488 (if (> reg-end (point)) 2741 (insert (concat " " word))))))))
2489 (setq reg-end (+ 1 reg-end (length word))))
2490 (insert (concat " " word)))))))
2491 reg-end)
2492 2742
2493 2743
2494(defconst ispell-version "2.37 -- Tue Jun 13 12:05:28 EDT 1995") 2744(defconst ispell-version "ispell.el 3.0 -- Tue Apr 28 14:40:01 PDT 1998")
2495 2745
2496(provide 'ispell) 2746(provide 'ispell)
2497 2747
@@ -2503,12 +2753,14 @@ Both should not be used to define a buffer-local dictionary."
2503;;; eval: expression 2753;;; eval: expression
2504;;; local-variable: value 2754;;; local-variable: value
2505 2755
2506;;; The following sets the buffer local dictionary to english! 2756;;; The following sets the buffer local dictionary to 'american' English
2757;;; and spell checks only comments.
2507 2758
2508;;; Local Variables: 2759;;; Local Variables:
2509;;; mode: emacs-lisp 2760;;; mode: emacs-lisp
2510;;; comment-column: 40 2761;;; comment-column: 40
2511;;; ispell-local-dictionary: "american" 2762;;; ispell-check-comments: exclusive
2763;;; Local IspellDict: "american"
2512;;; End: 2764;;; End:
2513 2765
2514 2766
@@ -2516,13 +2768,19 @@ Both should not be used to define a buffer-local dictionary."
2516 2768
2517;;; The following places this file in nroff parsing and extended char modes. 2769;;; The following places this file in nroff parsing and extended char modes.
2518;;; Local IspellParsing: nroff-mode ~nroff 2770;;; Local IspellParsing: nroff-mode ~nroff
2519;;; Change IspellDict to IspellDict: to enable the following line.
2520;;; Local IspellDict english
2521;;; Change IspellPersDict to IspellPersDict: to enable the following line. 2771;;; Change IspellPersDict to IspellPersDict: to enable the following line.
2522;;; Local IspellPersDict ~/.ispell_lisp 2772;;; Local IspellPersDict ~/.ispell_lisp
2523;;; The following were automatically generated by ispell using the 'A' command: 2773;;; The following were automatically generated by ispell using the 'A' command:
2524; LocalWords: ispell ispell-highlight-p ispell-check-comments query-replace 2774; LocalWords: Moellmann copyleft Dansk russian KOI charset minipage hspace mh
2525; LocalWords: ispell-query-replace-choices ispell-skip-tib non-nil tib 2775; LocalWords: unsplitable includeonly nocite epsfig displaymath eqnarray init
2526; LocalWords: regexps ispell-tib-ref-beginning ispell-tib-ref-end 2776; LocalWords: settable autoload inews frag pdict alist Wildcards iconify arg
2777; LocalWords: tex alists minibuffer Autoloading setq changelog kss stevens reg
2778; LocalWords: Castellano framepop sgml modeline Wedler Dirk Froembgen fn Gerd
2779; LocalWords: pgp NZST Vignaux autoloaded loaddefs aff Francais Nederlands SPC
2780; LocalWords: popup nonmenu regexp herr num pers dict unhighlight ccept uit NB
2781; LocalWords: buf grep sync prev inc hilight olddot AIX ersion msg read's op
2782; LocalWords: bufs pt regxp multibyte cmd Quinlan uuencoded esp unidiff eg sc
2783; LocalWords: VM lns HTML eval american IspellPersDict
2784
2785;;; ispell.el ends here
2527 2786
2528;; ispell.el ends here