ispell.el 127 KB
Newer Older
1
;;; ispell.el --- Interface to International Ispell Versions 3.1 and 3.2
Richard M. Stallman's avatar
Richard M. Stallman committed
2

3
;; Copyright (C) 1994, 1995, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
Richard M. Stallman's avatar
Richard M. Stallman committed
4

5 6 7 8
;; Author:	     Ken Stevens <k.stevens@ieee.org>
;; Maintainer:	     Ken Stevens <k.stevens@ieee.org>
;; Stevens Mod Date: Fri Aug  4 09:41:50 PDT 2000
;; Stevens Revision: 3.4
9
;; Status          : Release with 3.1.12+ and 3.2.0+ ispell.
10 11
;; Bug Reports     : ispell-el-bugs@itcorp.com
;; Web Site        : http://kdstevens.com/~stevens/ispell-page.html
Dave Love's avatar
Dave Love committed
12
;; Keywords: unix wp
Richard M. Stallman's avatar
Richard M. Stallman committed
13

Erik Naggum's avatar
Erik Naggum committed
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
;; This file is part of GNU Emacs.

;; GNU Emacs is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 2, or (at your option)
;; any later version.

;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs; see the file COPYING.  If not, write to the
;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.

;; Note: version numbers and time stamp are not updated
32
;;   when this file is edited for release with GNU emacs.
Richard M. Stallman's avatar
Richard M. Stallman committed
33

Richard M. Stallman's avatar
Richard M. Stallman committed
34 35
;;; Commentary:

Erik Naggum's avatar
Erik Naggum committed
36
;; INSTRUCTIONS
37

38 39 40 41
;;   This code contains a section of user-settable variables that you
;; should inspect prior to installation.  Look past the end of the history
;; list.  Set them up for your locale and the preferences of the majority
;; of the users.  Otherwise the users may need to set a number of variables
Erik Naggum's avatar
Erik Naggum committed
42
;; themselves.
43
;;   You particularly may want to change the default dictionary for your
Erik Naggum's avatar
Erik Naggum committed
44
;; country and language.
45 46 47 48
;;   Most dictionary changes should be made in this file so all users can
;; enjoy them.  Local or modified dictionaries are supported in your .emacs
;; file.  Modify the variable `ispell-local-dictionary-alist' to include
;; these dictionaries, and they will be installed when ispell.el is loaded.
49

Erik Naggum's avatar
Erik Naggum committed
50 51 52 53
;;  Depending on the mail system you use, you may want to include these:
;;  (add-hook 'news-inews-hook 'ispell-message)
;;  (add-hook 'mail-send-hook  'ispell-message)
;;  (add-hook 'mh-before-send-letter-hook 'ispell-message)
54

55
;;   Ispell has a TeX parser and a nroff parser (the default).
Erik Naggum's avatar
Erik Naggum committed
56 57 58
;; The parsing is controlled by the variable ispell-parser.  Currently
;; it is just a "toggle" between TeX and nroff, but if more parsers are
;; added it will be updated.  See the variable description for more info.
59 60


Erik Naggum's avatar
Erik Naggum committed
61
;; TABLE OF CONTENTS
62

Erik Naggum's avatar
Erik Naggum committed
63 64 65 66
;;   ispell-word
;;   ispell-region
;;   ispell-buffer
;;   ispell-message
67
;;   ispell-comments-and-strings
Erik Naggum's avatar
Erik Naggum committed
68 69 70 71 72 73
;;   ispell-continue
;;   ispell-complete-word
;;   ispell-complete-word-interior-frag
;;   ispell-change-dictionary
;;   ispell-kill-ispell
;;   ispell-pdict-save
74 75
;;   ispell-skip-region-alist

Erik Naggum's avatar
Erik Naggum committed
76 77
;; Commands in ispell-region:
;; Character replacement: Replace word with choice.  May query-replace.
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
;; ` ': Accept word this time.
;; `i': Accept word and insert into private dictionary.
;; `a': Accept word for this session.
;; `A': Accept word and place in buffer-local dictionary.
;; `r': Replace word with typed-in value.  Rechecked.
;; `R': Replace word with typed-in value. Query-replaced in buffer. Rechecked.
;; `?': Show these commands
;; `x': Exit spelling buffer.  Move cursor to original point.
;; `X': Exit spelling buffer.  Leaves cursor at the current point, and permits
;;      the check to be completed later.
;; `q': Quit spelling session (Kills ispell process).
;; `l': Look up typed-in replacement in alternate dictionary.  Wildcards okay.
;; `u': Like `i', but the word is lower-cased first.
;; `m': Place entered value in personal dictionary, then recheck current word.
;; `C-l': redraws screen
;; `C-r': recursive edit
;; `C-z': suspend emacs or iconify frame

Erik Naggum's avatar
Erik Naggum committed
96 97 98 99 100 101 102 103
;; Buffer-Local features:
;; There are a number of buffer-local features that can be used to customize
;;  ispell for the current buffer.  This includes language dictionaries,
;;  personal dictionaries, parsing, and local word spellings.  Each of these
;;  local customizations are done either through local variables, or by
;;  including the keyword and argument(s) at the end of the buffer (usually
;;  prefixed by the comment characters).  See the end of this file for
;;  examples.  The local keywords and variables are:
104

Erik Naggum's avatar
Erik Naggum committed
105 106 107 108 109 110
;;  ispell-dictionary-keyword   language-dictionary
;;      uses local variable ispell-local-dictionary
;;  ispell-pdict-keyword        personal-dictionary
;;      uses local variable ispell-local-pdict
;;  ispell-parsing-keyword      mode-arg extended-char-arg
;;  ispell-words-keyword        any number of local word spellings
111 112 113 114 115 116 117

;; Region skipping:
;;  Place new regular expression definitions of regions you prefer not to
;;  spell check in `ispell-skip-region-alist'.  Mode-dependent features can
;;  be added to latex by modifying `ispell-tex-skip-alists'.
;;  `ispell-message' contains some custom skipping code for e-mail messages.

Erik Naggum's avatar
Erik Naggum committed
118
;; BUGS:
119 120 121 122
;;  Need a way to select between different character mappings without separate
;;    dictionary entries.
;;  Multi-byte characters if not defined by current dictionary may result in the
;;    evil "misalignment error" in some versions of MULE emacs.
Erik Naggum's avatar
Erik Naggum committed
123
;;  On some versions of emacs, growing the minibuffer fails.
124
;;    see `ispell-help-in-bufferp'.
125 126
;;  Recursive edits (?C-r or ?R) inside a keyboard text replacement check (?r)
;;    can cause misalignment errors.
127 128 129 130 131

;; HISTORY

;; Modifications made in latest versions:

132 133 134 135 136 137 138 139
;; Revision 3.4 2000/8/4 09:41:50	kss
;; Support new color display functions.
;; Fixed misalignment offset bug when replacing a string after a shift made.
;; Set to standard Author/Maintainer heading,
;; ensure localwords lists are separated from the text by newline. (Dave Love)
;; Added dictionary definition for Italian (William Deakin)
;; HTML region skipping greatly improved. (Chuck D. Phillips)
;; improved menus.  Fixed regexp matching http/email addresses.
140 141 142
;; one arg always for xemacs sleep-for (gunnar Evermann)
;; support for synchronous processes (Eli Zaretskii)

143 144 145 146 147 148 149 150 151 152 153
;; Revision 3.3  1999/11/29 11:38:34     kss
;; Only word replacements entered in from the keyboard are rechecked.
;; This fixes a bug in tex parsing and misalignment.
;; Exceptions exist for recursive edit and query-replace, with tex error
;; condition tested.  Recursive editing improved.
;; XEmacs repair for when `enable-multibyte-characters' defined - Didier Verna.
;; ispell-help fixed for XEmacs.  Choices minibuffer now displayed in XEmacs.
;; Only list valid dictionaries in Spell menu.  Russian dictionary doesn't allow
;; run-together words, and uses koi8-r font.  Don't skip text in html <TT>
;; fonts.

154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
;; Revision 3.2  1999/5/7 14:25:14	kss
;; Accept ispell versions 3.X.Y where X>=1
;; fine tuned latex region skipping.  Fixed bug in ispell-word that did not
;; point in right place on words < 2 chars.  Simplified ispell-minor-mode.
;; Fixed bug in TeX parsing when math commands are in the comments.
;; Removed calls to `when' macro.

;; Revision 3.1  1998/12/1 13:21:52	kss
;; Improved and fixed customize support.
;; Improved and fixed comments in variables and messages.
;; A coding system is now required for all languages.
;; casechars improved for castellano, castellano8, and norsk dictionaries.
;; Dictionary norsk7-tex removed.  Dictionary polish added.
;; Dictionaries redefined at load-time to support dictionary changes.
;; Menu redefined at load time to support dictionary changes.
;; ispell-check-version added as an alias for `check-ispell-version'.
;; Spelling suggestions returned in order generated by ispell.
;; Small bug fixed in matching ispell error messages.
;; Robustness added to ensure `case-fold-search' doesn't get redefined.
;; Fixed bug that didn't respect case of word in `ispell-complete-word'.
;; Multibyte character coding support added for process interactions.
;; Ensure ispell process has terminated before starting new process.
;;  This can otherwise confuse process filters and hang ispell.
177
;; Improved skipping support for SGML.
178 179 180
;; Fixed bug using ^M rather than \r in `ispell-minor-check'.
;; Improved message reference matching in `ispell-message'.
;; Fixed bug in returning to nroff mode from tex mode.
Richard M. Stallman's avatar
Richard M. Stallman committed
181

182

Richard M. Stallman's avatar
Richard M. Stallman committed
183 184
;;; Code:

185 186 187 188 189 190 191
;;; Custom.el macros require recompiling this when they are not present.
;;; Add in backward compatible custom support.
(eval-when-compile
  (if (not (fboundp 'defcustom))
      (defmacro defcustom (symbol value doc &rest args)
	"Empty replacement for defcustom when not supplied."
	`(defvar ,symbol ,value ,doc))))
Richard M. Stallman's avatar
Richard M. Stallman committed
192

193 194 195 196 197
(eval-when-compile
  (if (fboundp 'defgroup)
      (defgroup ispell nil
	"User variables for emacs ispell interface."
	:group 'applications)))
198

199 200 201
(if (not (fboundp 'buffer-substring-no-properties))
    (defun buffer-substring-no-properties (start end)
      (buffer-substring start end)))
202

203
;;;###autoload
204
(defconst xemacsp (string-match "Lucid\\|XEmacs" emacs-version)
205 206 207
  "Non nil if using XEmacs.")

;;;###autoload
208
(defconst version18p (string-match "18\\.[0-9]+\\.[0-9]+" emacs-version)
209 210 211
  "Non nil if using emacs version 18.")

;;;###autoload
212
(defconst version20p (string-match "20\\.[0-9]+\\.[0-9]+" emacs-version)
213 214
  "Non nil if using emacs version 20.")

215 216 217 218 219 220
(defconst ispell-graphic-p
  (if (fboundp 'display-graphic-p)
      (display-graphic-p)
    xemacsp)
  "True if running on a `graphics capable' display.")

221 222 223 224
(and (not version18p)
     (not (boundp 'epoch::version))
     (defalias 'ispell-check-version 'check-ispell-version))

225

226 227 228 229 230 231
;;; **********************************************************************
;;; The following variables should be set according to personal preference
;;; and location of binaries:
;;; **********************************************************************


232
;;;  ******* THIS FILE IS WRITTEN FOR ISPELL VERSION 3.1+
233 234 235 236

(defcustom ispell-highlight-p 'block
  "*Highlight spelling errors when non-nil.
When set to `block', assumes a block cursor with TTY displays."
237
  :type '(choice (const block) (const :tag "off" nil) (const :tag "on" t))
238 239 240
  :group 'ispell)

(defcustom ispell-highlight-face 'highlight
Richard M. Stallman's avatar
Richard M. Stallman committed
241 242 243
  "*The face used for Ispell highlighting.  For Emacses with overlays.
Possible values are `highlight', `modeline', `secondary-selection',
`region', and `underline'.
Richard M. Stallman's avatar
Richard M. Stallman committed
244 245
This variable can be set by the user to whatever face they desire.
It's most convenient if the cursor color and highlight color are
246 247 248
slightly different."
  :type 'face
  :group 'ispell)
Richard M. Stallman's avatar
Richard M. Stallman committed
249

250
(defcustom ispell-check-comments t
251 252 253 254
  "*Spelling of comments checked when non-nil.
When set to `exclusive', ONLY comments are checked.  (For code comments).
Warning!  Not checking comments, when a comment start is embedded in strings,
may produce undesired results."
255
  :type '(choice (const exclusive) (const :tag "off" nil) (const :tag "on" t))
256
  :group 'ispell)
Richard M. Stallman's avatar
Richard M. Stallman committed
257

258
(defcustom ispell-query-replace-choices nil
Richard M. Stallman's avatar
Richard M. Stallman committed
259
  "*Corrections made throughout region when non-nil.
260 261 262
Uses `query-replace' (\\[query-replace]) for corrections."
  :type 'boolean
  :group 'ispell)
Richard M. Stallman's avatar
Richard M. Stallman committed
263

264
(defcustom ispell-skip-tib nil
Richard M. Stallman's avatar
Richard M. Stallman committed
265
  "*Does not spell check `tib' bibliography references when non-nil.
Richard M. Stallman's avatar
Richard M. Stallman committed
266
Skips any text between strings matching regular expressions
Richard M. Stallman's avatar
Richard M. Stallman committed
267
`ispell-tib-ref-beginning' and `ispell-tib-ref-end'.
Richard M. Stallman's avatar
Richard M. Stallman committed
268 269

TeX users beware:  Any field starting with [. will skip until a .] -- even
Richard M. Stallman's avatar
Richard M. Stallman committed
270
your whole buffer -- unless you set `ispell-skip-tib' to nil.  That includes
271 272 273
a [.5mm] type of number...."
  :type 'boolean
  :group 'ispell)
Richard M. Stallman's avatar
Richard M. Stallman committed
274 275 276 277 278 279 280

(defvar ispell-tib-ref-beginning "[[<]\\."
  "Regexp matching the beginning of a Tib reference.")

(defvar ispell-tib-ref-end "\\.[]>]"
  "Regexp matching the end of a Tib reference.")

281
(defcustom ispell-keep-choices-win t
Richard M. Stallman's avatar
Richard M. Stallman committed
282
  "*When not nil, the `*Choices*' window remains for spelling session.
283 284 285
This minimizes redisplay thrashing."
  :type 'boolean
  :group 'ispell)
Richard M. Stallman's avatar
Richard M. Stallman committed
286

287
(defcustom ispell-choices-win-default-height (if ispell-graphic-p 3 2)
288 289
  "*The default size of the `*Choices*' window, including mode line.
Must be greater than 1.
290 291 292
A Graphic capable modeline is thicker than a line of text, so it partially
covers the last line of text in the choices buffer.  Include an extra line
for graphic capable displays to see all of the choices clearly."
293 294
  :type 'integer
  :group 'ispell)
Richard M. Stallman's avatar
Richard M. Stallman committed
295

296 297 298 299
(defcustom ispell-program-name "ispell"
  "Program invoked by \\[ispell-word] and \\[ispell-region] commands."
  :type 'string
  :group 'ispell)
Richard M. Stallman's avatar
Richard M. Stallman committed
300

301
(defcustom ispell-alternate-dictionary
Richard M. Stallman's avatar
Richard M. Stallman committed
302
  (cond ((file-exists-p "/usr/dict/web2") "/usr/dict/web2")
303
	((file-exists-p "/usr/share/dict/web2") "/usr/share/dict/web2")
Richard M. Stallman's avatar
Richard M. Stallman committed
304 305
	((file-exists-p "/usr/dict/words") "/usr/dict/words")
	((file-exists-p "/usr/lib/dict/words") "/usr/lib/dict/words")
306
	((file-exists-p "/usr/share/dict/words") "/usr/share/dict/words")
Richard M. Stallman's avatar
Richard M. Stallman committed
307 308
	((file-exists-p "/sys/dict") "/sys/dict")
	(t "/usr/dict/words"))
309
  "*Alternate dictionary for spelling help."
310
  :type '(choice file (const :tag "None" nil))
311
  :group 'ispell)
Richard M. Stallman's avatar
Richard M. Stallman committed
312

313 314
(defcustom ispell-complete-word-dict ispell-alternate-dictionary
  "*Dictionary used for word completion."
315
  :type '(choice file (const :tag "None" nil))
316
  :group 'ispell)
Richard M. Stallman's avatar
Richard M. Stallman committed
317

318 319 320 321 322 323 324 325 326 327
(defcustom ispell-message-dictionary-alist nil
  "*List used by `ispell-message' to select a new dictionary.
It consists of pairs (REGEXP . DICTIONARY).  If REGEXP is found
in the message headers, `ispell-local-dictionary' will be set to
DICTIONARY if `ispell-local-dictionary' is not buffer-local.
E.g. you may use the following value:
  '((\"^Newsgroups:[ \\t]*de\\\\.\" . \"deutsch8\")
    (\"^To:[^\\n,]+\\\\.de[ \\t\\n,>]\" . \"deutsch8\"))"
  :type '(repeat (cons regexp string))
  :group 'ispell)
Richard M. Stallman's avatar
Richard M. Stallman committed
328

329 330 331 332 333 334 335

(defcustom ispell-grep-command "egrep"
  "Name of the grep command for search processes."
  :type 'string
  :group 'ispell)

(defcustom ispell-grep-options "-i"
Richard M. Stallman's avatar
Richard M. Stallman committed
336
  "String of options to use when running the program in `ispell-grep-command'.
Richard M. Stallman's avatar
Richard M. Stallman committed
337
Should probably be \"-i\" or \"-e\".
338 339 340
Some machines (like the NeXT) don't support \"-i\""
  :type 'string
  :group 'ispell)
Richard M. Stallman's avatar
Richard M. Stallman committed
341

342 343 344 345 346
(defcustom ispell-look-command
  (cond ((file-exists-p "/bin/look") "/bin/look")
	((file-exists-p "/usr/local/bin/look") "/usr/local/bin/look")
	((file-exists-p "/usr/bin/look") "/usr/bin/look")
	(t "look"))
Richard M. Stallman's avatar
Richard M. Stallman committed
347
  "Name of the look command for search processes.
348 349 350
This must be an absolute file name."
  :type 'file
  :group 'ispell)
Richard M. Stallman's avatar
Richard M. Stallman committed
351

352
(defcustom ispell-look-p (file-exists-p ispell-look-command)
353
  "*Non-nil means use `look' rather than `grep'.
354 355 356
Default is based on whether `look' seems to be available."
  :type 'boolean
  :group 'ispell)
Richard M. Stallman's avatar
Richard M. Stallman committed
357

358 359 360 361
(defcustom ispell-have-new-look nil
  "*Non-nil means use the `-r' option (regexp) when running `look'."
  :type 'boolean
  :group 'ispell)
Richard M. Stallman's avatar
Richard M. Stallman committed
362

363 364 365 366
(defcustom ispell-look-options (if ispell-have-new-look "-dfr" "-df")
  "String of command options for `ispell-look-command'."
  :type 'string
  :group 'ispell)
Richard M. Stallman's avatar
Richard M. Stallman committed
367

368
(defcustom ispell-use-ptys-p nil
Richard M. Stallman's avatar
Richard M. Stallman committed
369
  "When non-nil, Emacs uses ptys to communicate with Ispell.
370 371 372
When nil, Emacs uses pipes."
  :type 'boolean
  :group 'ispell)
Richard M. Stallman's avatar
Richard M. Stallman committed
373

374
(defcustom ispell-following-word nil
Richard M. Stallman's avatar
Richard M. Stallman committed
375
  "*Non-nil means `ispell-word' checks the word around or after point.
376 377 378
Otherwise `ispell-word' checks the preceding word."
  :type 'boolean
  :group 'ispell)
Richard M. Stallman's avatar
Richard M. Stallman committed
379

380
(defcustom ispell-help-in-bufferp nil
Richard M. Stallman's avatar
Richard M. Stallman committed
381
  "*Non-nil means display interactive keymap help in a buffer.
382
The following values are supported:
383 384 385 386
  nil        Expand the minibuffer and display a short help message
             there for a couple of seconds.
  t          Pop up a new buffer and display a short help message there
             for a couple of seconds.
387
  electric   Pop up a new buffer and display a long help message there.
388
             User can browse and then exit the help mode."
389
  :type '(choice (const electric) (const :tag "off" nil) (const :tag "on" t))
390
  :group 'ispell)
Richard M. Stallman's avatar
Richard M. Stallman committed
391

392 393 394 395
(defcustom ispell-quietly nil
  "*Non-nil means suppress messages in `ispell-word'."
  :type 'boolean
  :group 'ispell)
Richard M. Stallman's avatar
Richard M. Stallman committed
396

397
(defcustom ispell-format-word (function upcase)
Richard M. Stallman's avatar
Richard M. Stallman committed
398
  "*Formatting function for displaying word being spell checked.
399 400 401
The function must take one string argument and return a string."
  :type 'function
  :group 'ispell)
Richard M. Stallman's avatar
Richard M. Stallman committed
402

403 404 405 406 407 408 409 410
(defcustom ispell-use-framepop-p nil
  "When non-nil ispell uses framepop to display choices in a dedicated frame.
You can set this variable to dynamically use framepop if you are in a
window system by evaluating the following on startup to set this variable:
  (and window-system (condition-case () (require 'framepop) (error nil)))"
  :type 'boolean
  :group 'ispell)

411
;;;###autoload
412
(defcustom ispell-personal-dictionary nil
413 414
  "*File name of your personal spelling dictionary, or nil.
If nil, the default personal dictionary, \"~/.ispell_DICTNAME\" is used,
415
where DICTNAME is the name of your default dictionary."
416 417
  :type '(choice file
		 (const :tag "default" nil))
418
  :group 'ispell)
Richard M. Stallman's avatar
Richard M. Stallman committed
419

420 421 422 423
(defcustom ispell-silently-savep nil
  "*When non-nil, save the personal dictionary without confirmation."
  :type 'boolean
  :group 'ispell)
Richard M. Stallman's avatar
Richard M. Stallman committed
424

425 426 427 428 429 430 431
;;; This is the local dictionary to use.  When nil the default dictionary will
;;; be used.  Change set-default call to use a new default dictionary.
(defcustom ispell-local-dictionary nil
  "If non-nil, the dictionary to be used for Ispell commands.
The value must be a string dictionary name in `ispell-dictionary-alist'.
This variable becomes buffer-local when set in any fashion.

432
Setting `ispell-local-dictionary' to a value has the same effect as
433 434 435 436
calling \\[ispell-change-dictionary] with that value.  This variable
is automatically set when defined in the file with either
`ispell-dictionary-keyword' or the Local Variable syntax.

437 438
To create a non-standard default dictionary (not from `ispell-dictionary-alist')
call function `set-default' with the new dictionary name."
439 440 441 442 443 444 445 446
  :type '(choice string
		 (const :tag "default" nil))
  :group 'ispell)

(make-variable-buffer-local 'ispell-local-dictionary)

;; Call this function set up the default dictionary if not English.
;;(set-default 'ispell-local-dictionary nil)
Richard M. Stallman's avatar
Richard M. Stallman committed
447 448


449
(defcustom ispell-extra-args nil
Richard M. Stallman's avatar
Richard M. Stallman committed
450
  "*If non-nil, a list of extra switches to pass to the Ispell program.
451
For example, (\"-W\" \"3\") to cause it to accept all 1-3 character
Richard M. Stallman's avatar
Richard M. Stallman committed
452
words as correct.  See also `ispell-dictionary-alist', which may be used
453 454 455
for language-specific arguments."
  :type '(repeat string)
  :group 'ispell)
Richard M. Stallman's avatar
Richard M. Stallman committed
456

457

458

459
(defcustom ispell-skip-html 'use-mode-name
460 461 462 463 464 465 466 467 468
  "*Indicates whether ispell should skip spell checking of SGML markup.
If t, always skip SGML markup; if nil, never skip; if non-t and non-nil,
guess whether SGML markup should be skipped according to the name of the
buffer's major mode."
  :type '(choice (const :tag "always" t) (const :tag "never" nil)
		 (const :tag "use-mode-name" use-mode-name))
  :group 'ispell)


469
;;; Define definitions here only for personal dictionaries.
470
;;;###autoload
471 472 473 474 475 476 477 478 479 480 481 482 483 484 485
(defcustom ispell-local-dictionary-alist nil
  "*Contains local or customized dictionary definitions.
See `ispell-dictionary-alist'."
  :type '(repeat (list (choice :tag "Dictionary"
			       (string :tag "Dictionary name")
			       (const :tag "default" nil))
		       (regexp :tag "Case characters")
		       (regexp :tag "Non case characters")
		       (regexp :tag "Other characters")
		       (boolean :tag "Many other characters")
		       (repeat :tag "Ispell command line args"
			       (string :tag "Arg"))
		       (choice :tag "Extended character mode"
			       (const "~tex") (const "~plaintex")
			       (const "~nroff") (const "~list")
486
			       (const "~latin1") (const "~latin3")
487 488 489
 			       (const :tag "default" nil))
		       (choice :tag "Character set"
			       (const iso-8859-1)
490 491
			       (const iso-8859-2)
			       (const koi8-r))))
492 493 494
  :group 'ispell)


495 496
;;; split dictionary so line length is smaller in loaddefs.el

497
;;; First part of dictionary, shortened for loaddefs.el
498
;;;###autoload
499 500 501 502
(setq
 ispell-dictionary-alist-1
 '((nil					; default (English.aff)
    "[A-Za-z]" "[^A-Za-z]" "[']" nil ("-B") nil iso-8859-1)
503
   ("american"				; Yankee English
504
    "[A-Za-z]" "[^A-Za-z]" "[']" nil ("-B") nil iso-8859-1)
505
   ("brasileiro"			; Brazilian mode
506 507 508
    "[A-Z\301\311\315\323\332\300\310\314\322\331\303\325\307\334\302\312\324a-z\341\351\355\363\372\340\350\354\362\371\343\365\347\374\342\352\364]"
    "[^A-Z\301\311\315\323\332\300\310\314\322\331\303\325\307\334\302\312\324a-z\341\351\355\363\372\340\350\354\362\371\343\365\347\374\342\352\364]"
    "[']" nil ("-d" "brasileiro") nil iso-8859-1)
509 510 511 512 513
   ("british"				; British version
    "[A-Za-z]" "[^A-Za-z]" "[']" nil ("-B" "-d" "british") nil iso-8859-1)
   ("castellano"			; Spanish mode
    "[A-Z\301\311\315\321\323\332\334a-z\341\351\355\361\363\372\374]"
    "[^A-Z\301\311\315\321\323\332\334a-z\341\351\355\361\363\372\374]"
514
    "[-]" nil ("-B" "-d" "castellano") "~tex" iso-8859-1)
515 516 517
   ("castellano8"			; 8 bit Spanish mode
    "[A-Z\301\311\315\321\323\332\334a-z\341\351\355\361\363\372\374]"
    "[^A-Z\301\311\315\321\323\332\334a-z\341\351\355\361\363\372\374]"
518
    "[-]" nil ("-B" "-d" "castellano") "~latin1" iso-8859-1)))
519 520 521 522 523 524 525


;;; Second part of dictionary, shortened for loaddefs.el
;;;###autoload
(setq
 ispell-dictionary-alist-2
 '(("czech"
526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541
    "[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]"
    "[^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]"
    "" nil ("-B" "-d" "czech") nil iso-8859-2)
   ("dansk"				; Dansk.aff
    "[A-Z\306\330\305a-z\346\370\345]" "[^A-Z\306\330\305a-z\346\370\345]"
    "[']" nil ("-C") nil iso-8859-1)
   ("deutsch"				; Deutsch.aff
    "[a-zA-Z\"]" "[^a-zA-Z\"]" "[']" t ("-C") "~tex" iso-8859-1)
   ("deutsch8"
    "[a-zA-Z\304\326\334\344\366\337\374]"
    "[^a-zA-Z\304\326\334\344\366\337\374]"
    "[']" t ("-C" "-d" "deutsch") "~latin1" iso-8859-1)
   ("english"				; make English explicitly selectable
    "[A-Za-z]" "[^A-Za-z]" "[']" nil ("-B") nil iso-8859-1)))


542
;;; Third part of dictionary, shortened for loaddefs.el
543
;;;###autoload
544
(setq
545
 ispell-dictionary-alist-3
546 547 548 549 550 551 552 553 554 555 556 557
 '(("esperanto"
    "[A-Za-z\246\254\266\274\306\330\335\336\346\370\375\376]"
    "[^A-Za-z\246\254\266\274\306\330\335\336\346\370\375\376]"
    "[-']" t ("-C") "~latin3" iso-8859-1)
   ("esperanto-tex"
    "[A-Za-z^\\]" "[^A-Za-z^\\]"
    "[-'`\"]" t ("-C" "-d" "esperanto") "~tex" iso-8859-1)
   ("francais7"
    "[A-Za-z]" "[^A-Za-z]" "[`'^---]" t nil nil iso-8859-1)
   ("francais"				; Francais.aff
    "[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]"
    "[^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]"
558
    "[-']" t nil "~list" iso-8859-1)))
559 560 561 562 563 564 565


;;; Fourth part of dictionary, shortened for loaddefs.el
;;;###autoload
(setq
 ispell-dictionary-alist-4
 '(("francais-tex"			; Francais.aff
566 567
    "[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\\]"
    "[^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\\]"
568 569 570 571 572
    "[-'^`\"]" t nil "~tex" iso-8859-1)
   ("italiano"                         ; Italian.aff
    "[A-Z\300\301\310\311\314\315\322\323\331\332a-z\340\341\350\351\354\355\363\371\372]"
    "[^A-Z\300\301\310\311\314\315\322\323\331\332a-z\340\341\350\351\354\355\363\371\372]"
    "[-]" nil ("-B" "-d" "italian") "~tex" iso-8859-1)
573 574 575 576 577 578 579
   ("nederlands"			; Nederlands.aff
    "[A-Za-z\300-\305\307\310-\317\322-\326\331-\334\340-\345\347\350-\357\361\362-\366\371-\374]"
    "[^A-Za-z\300-\305\307\310-\317\322-\326\331-\334\340-\345\347\350-\357\361\362-\366\371-\374]"
    "[']" t ("-C") nil iso-8859-1)
   ("nederlands8"			; Dutch8.aff
    "[A-Za-z\300-\305\307\310-\317\322-\326\331-\334\340-\345\347\350-\357\361\362-\366\371-\374]"
    "[^A-Za-z\300-\305\307\310-\317\322-\326\331-\334\340-\345\347\350-\357\361\362-\366\371-\374]"
580 581 582 583 584 585 586 587
    "[']" t ("-C") nil iso-8859-1)))


;;; Fifth part of dictionary, shortened for loaddefs.el
;;;###autoload
(setq
 ispell-dictionary-alist-5
 '(("norsk"				; 8 bit Norwegian mode
588 589 590 591 592 593
    "[A-Za-z\305\306\307\310\311\322\324\330\345\346\347\350\351\362\364\370]"
    "[^A-Za-z\305\306\307\310\311\322\324\330\345\346\347\350\351\362\364\370]"
    "[\"]" nil ("-d" "norsk") "~list" iso-8859-1)
   ("norsk7-tex"			; 7 bit Norwegian TeX mode
    "[A-Za-z{}\\'^`]" "[^A-Za-z{}\\'^`]"
    "[\"]" nil ("-d" "norsk") "~plaintex" iso-8859-1)
594
   ("polish"				; polish mode
595 596
    "[A-Za-z\241\243\246\254\257\261\263\266\274\277\306\312\321\323\346\352\361\363]"
    "[^A-Za-z\241\243\246\254\257\261\263\266\274\277\306\312\321\323\346\352\361\363]"
597 598 599 600 601 602 603
    "" nil ( "-d" "polish") nil iso-8859-2)))


;;; Sixth part of dictionary, shortened for loaddefs.el
;;;###autoload
(setq
 ispell-dictionary-alist-6
604 605
 ;; include Russian iso character set too?
 ;;   "[']" t ("-d" "russian") "~latin1" iso-8859-1
606
 '(("russian"				; Russian.aff (KOI8-R charset)
607 608
    "[\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]"
    "[^\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]"
609
    "" nil ("-d" "russian") nil koi8-r)
610 611 612 613 614
   ("svenska"				; Swedish mode
    "[A-Za-z\345\344\366\351\340\374\350\346\370\347\305\304\326\311\300\334\310\306\330\307]"
    "[^A-Za-z\345\344\366\351\340\374\350\346\370\347\305\304\326\311\300\334\310\306\330\307]"
    "[']" nil ("-C") "~list" iso-8859-1)))

615

616

617
;;;###autoload
618
(defcustom ispell-dictionary-alist
619 620
  (append ispell-local-dictionary-alist	; dictionary customizations
	  ispell-dictionary-alist-1 ispell-dictionary-alist-2
621 622
	  ispell-dictionary-alist-3 ispell-dictionary-alist-4
	  ispell-dictionary-alist-5 ispell-dictionary-alist-6)
Richard M. Stallman's avatar
Richard M. Stallman committed
623 624 625 626
  "An alist of dictionaries and their associated parameters.

Each element of this list is also a list:

Richard M. Stallman's avatar
Richard M. Stallman committed
627
\(DICTIONARY-NAME CASECHARS NOT-CASECHARS OTHERCHARS MANY-OTHERCHARS-P
628
        ISPELL-ARGS EXTENDED-CHARACTER-MODE CHARACTER-SET\)
Richard M. Stallman's avatar
Richard M. Stallman committed
629

630 631
DICTIONARY-NAME is a possible string value of variable `ispell-dictionary',
nil means the default dictionary.
Richard M. Stallman's avatar
Richard M. Stallman committed
632 633 634 635 636 637

CASECHARS is a regular expression of valid characters that comprise a
word.

NOT-CASECHARS is the opposite regexp of CASECHARS.

638 639 640
OTHERCHARS is a regexp of characters in the NOT-CASECHARS set but which can be
used to construct words in some special way.  If OTHERCHARS characters follow
and precede characters from CASECHARS, they are parsed as part of a word,
641
otherwise they become word-breaks.  As an example in English, assume the
642
regular expression \"[']\" for OTHERCHARS.  Then \"they're\" and
643 644
\"Steven's\" are parsed as single words including the \"'\" character, but
\"Stevens'\" does not include the quote character as part of the word.
645
If you want OTHERCHARS to be empty, use the empty string.
Richard M. Stallman's avatar
Richard M. Stallman committed
646 647
Hint: regexp syntax requires the hyphen to be declared first here.

648 649 650
MANY-OTHERCHARS-P is non-nil when multiple OTHERCHARS are allowed in a word.
Otherwise only a single OTHERCHARS character is allowed to be part of any
single word.
Richard M. Stallman's avatar
Richard M. Stallman committed
651 652 653 654 655

ISPELL-ARGS is a list of additional arguments passed to the ispell
subprocess.

EXTENDED-CHARACTER-MODE should be used when dictionaries are used which
656
have been configured in an Ispell affix file.  (For example, umlauts
Richard M. Stallman's avatar
Richard M. Stallman committed
657
can be encoded as \\\"a, a\\\", \"a, ...)  Defaults are ~tex and ~nroff
Richard M. Stallman's avatar
Richard M. Stallman committed
658 659
in English.  This has the same effect as the command-line `-T' option.
The buffer Major Mode controls Ispell's parsing in tex or nroff mode,
Richard M. Stallman's avatar
Richard M. Stallman committed
660 661
but the dictionary can control the extended character mode.
Both defaults can be overruled in a buffer-local fashion. See
Richard M. Stallman's avatar
Richard M. Stallman committed
662
`ispell-parsing-keyword' for details on this.
Richard M. Stallman's avatar
Richard M. Stallman committed
663

664 665
CHARACTER-SET used for languages with multibyte characters.

Richard M. Stallman's avatar
Richard M. Stallman committed
666 667
Note that the CASECHARS and OTHERCHARS slots of the alist should
contain the same character set as casechars and otherchars in the
668 669 670 671 672 673 674 675 676 677 678
LANGUAGE.aff file \(e.g., english.aff\)."
  :type '(repeat (list (choice :tag "Dictionary"
			       (string :tag "Dictionary name")
			       (const :tag "default" nil))
		       (regexp :tag "Case characters")
		       (regexp :tag "Non case characters")
		       (regexp :tag "Other characters")
		       (boolean :tag "Many other characters")
		       (repeat :tag "Ispell command line args"
			       (string :tag "Arg"))
		       (choice :tag "Extended character mode"
679 680
			       (const "~tex") (const "~plaintex")
			       (const "~nroff") (const "~list")
681
			       (const "~latin1") (const "~latin3")
682
 			       (const :tag "default" nil))
683
		       (choice :tag "Character set"
684
			       (const iso-8859-1)
685 686
			       (const iso-8859-2)
			       (const koi8-r))))
687 688
  :group 'ispell)

689
;;; update the dictionaries at load time
690 691 692 693 694
(setq ispell-dictionary-alist
      (append ispell-local-dictionary-alist	; dictionary customizations
	      ispell-dictionary-alist-1 ispell-dictionary-alist-2
	      ispell-dictionary-alist-3 ispell-dictionary-alist-4
	      ispell-dictionary-alist-5 ispell-dictionary-alist-6))
695

696 697 698 699 700 701 702



;;; **********************************************************************
;;; The following are used by ispell, and should not be changed.
;;; **********************************************************************

Richard M. Stallman's avatar
Richard M. Stallman committed
703

704 705 706 707 708 709 710 711

;;; The version must be 3.1 or greater for this version of ispell.el
;;; There is an incompatibility between version 3.1.12 and lower versions.
(defconst ispell-required-version '(3 1 12)
  "Ispell versions with which this version of ispell.el is known to work.")
(defvar ispell-offset -1
  "Offset that maps protocol differences between ispell 3.1 versions.")

712
(defconst ispell-version "ispell.el 3.4 -- Fri Aug  4 09:41:50 PDT 2000")
713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778


(defun check-ispell-version (&optional interactivep)
  "Ensure that `ispell-program-name' is valid and the correct version.
Returns version number if called interactively.
Otherwise returns the library path if defined."
  ;; This is a little wasteful as we actually launch ispell twice: once
  ;; to make sure it's the right version, and once for real.  But people
  ;; get confused by version mismatches *all* the time (and I've got the
  ;; email to prove it) so I think this is worthwhile.  And the -v[ersion]
  ;; option is the only way I can think of to do this that works with
  ;; all versions, since versions earlier than 3.0.09 didn't identify
  ;; themselves on startup.
  (interactive "p")
  (let ((case-fold-search-val case-fold-search)
	;; avoid bugs when syntax of `.' changes in various default modes
	(default-major-mode 'fundamental-mode)
	result status)
    (save-excursion
      (set-buffer (get-buffer-create " *ispell-tmp*"))
      (erase-buffer)
      (setq status (call-process ispell-program-name nil t nil "-vv"))
      (goto-char (point-min))
      (if interactivep
	  (progn
	    (end-of-line)
	    (setq result (concat (buffer-substring-no-properties (point-min)
								 (point))
				 ", "
				 ispell-version))
	    (message result))
	;; return library path.
	(re-search-forward "LIBDIR = \\\"\\([^ \t\n]*\\)\\\"" nil t)
	(if (match-beginning 0)
	    (setq result (buffer-substring (match-beginning 1) (match-end 1)))))
      (goto-char (point-min))
      (if (not (memq status '(0 nil)))
	  (error "%s exited with %s %s" ispell-program-name
		 (if (stringp status) "signal" "code") status))
      (setq case-fold-search t
	    status (re-search-forward
		    (concat "\\<\\("
			    (format "%d" (car ispell-required-version))
			    "\\)\\.\\([0-9]*\\)\\.\\([0-9]*\\)\\>")
		    nil t)
	    case-fold-search case-fold-search-val)
      (if (or (not status)	; major version mismatch
	      (< (car (read-from-string (buffer-substring-no-properties
					 (match-beginning 2) (match-end 2))))
		 (car (cdr ispell-required-version)))) ; minor version mismatch
	  (error "%s version 3 release %d.%d.%d or greater is required"
		 ispell-program-name (car ispell-required-version)
		 (car (cdr ispell-required-version))
		 (car (cdr (cdr ispell-required-version))))
	;; check that it is the correct version.
	(if (and (= (car (read-from-string (buffer-substring-no-properties
					    (match-beginning 2)(match-end 2))))
		    (car (cdr ispell-required-version)))
		 (< (car (read-from-string (buffer-substring-no-properties
					    (match-beginning 3)(match-end 3))))
		    (car (cdr (cdr ispell-required-version)))))
	    (setq ispell-offset 0)))
      (kill-buffer (current-buffer)))
    result))


779 780 781 782 783 784

;;; The preparation of the menu bar menu must be autoloaded
;;; because otherwise this file gets autoloaded every time Emacs starts
;;; so that it can set up the menus and determine keyboard equivalents.


785
;;;###autoload
786 787
(defvar ispell-menu-map nil "Key map for ispell menu.")
;;; redo menu when loading ispell to get dictionary modifications
Karl Heuer's avatar
Karl Heuer committed
788
(setq ispell-menu-map nil)
Richard M. Stallman's avatar
Richard M. Stallman committed
789

790
;;;###autoload
791 792 793 794
(defvar ispell-menu-xemacs nil
  "Spelling menu for XEmacs.
If nil when package is loaded, a standard menu will be set,
and added as a submenu of the \"Edit\" menu.")
795

796
;;; Break out XEmacs menu and split into several calls to avoid having
797
;;; long lines in loaddefs.el.  Detect need off following constant.
798

799
;;; Set up dictionary
800
;;;###autoload
801
(defvar ispell-menu-map-needed
802
  ;; only needed when not version 18 and not XEmacs.
803
  (and (not ispell-menu-map)
804 805
       (not version18p)
       (not xemacsp)
806 807 808 809 810
       'reload))

(defvar ispell-library-path (check-ispell-version)
  "The directory where ispell dictionaries reside.")

811 812 813 814 815 816 817 818 819 820 821
(defvar ispell-process nil
  "The process object for Ispell.")

(defvar ispell-async-processp (and (fboundp 'kill-process)
				   (fboundp 'process-send-string)
				   (fboundp 'accept-process-output)
				   ;;(fboundp 'start-process)
				   ;;(fboundp 'set-process-filter)
				   ;;(fboundp 'process-kill-without-query)
				   )
  "Non-nil means that the OS supports asynchronous processes.")
822

823
;;;###autoload
824 825
(if ispell-menu-map-needed
    (let ((dicts (reverse (cons (cons "default" nil) ispell-dictionary-alist)))
826 827 828
	  ;; `ispell-library-path' intentionally not defined in autoload
	  (path (and (boundp 'ispell-library-path) ispell-library-path))
	  name load-dict)
829
      (setq ispell-menu-map (make-sparse-keymap "Spell"))
830
      ;; add the dictionaries to the bottom of the list.
831 832
      (while dicts
	(setq name (car (car dicts))
833
	      load-dict (car (cdr (member "-d" (nth 5 (car dicts)))))
834
	      dicts (cdr dicts))
835 836 837
	(cond ((not (stringp name))
	       (define-key ispell-menu-map (vector 'default)
		 (cons "Select Default Dict"
838 839 840
		       (cons "Dictionary for which Ispell was configured"
			     (list 'lambda () '(interactive)
				   (list
841
				     'ispell-change-dictionary "default"))))))
842 843 844 845 846 847 848
	      ((or (not path)		; load all if library dir not defined
		   (file-exists-p (concat path "/" name ".hash"))
		   (file-exists-p (concat path "/" name ".has"))
		   (and load-dict
			(or (file-exists-p(concat path "/" load-dict ".hash"))
			    (file-exists-p(concat path "/" load-dict ".has")))))
	       (define-key ispell-menu-map (vector (intern name))
849
		 (cons (concat "Select " (capitalize name) " Dict")
850 851 852
		       (list 'lambda () '(interactive)
			     (list 'ispell-change-dictionary name)))))))))

853

854
;;; define commands in menu in opposite order you want them to appear.
855
;;;###autoload
856 857 858
(if ispell-menu-map-needed
    (progn
      (define-key ispell-menu-map [ispell-change-dictionary]
859 860
	'(menu-item "Change Dictionary..." ispell-change-dictionary
		    :help "Supply explicit path to dictionary"))
861
      (define-key ispell-menu-map [ispell-kill-ispell]
862
	'(menu-item "Kill Process" ispell-kill-ispell
863
		    :enable (and ispell-process
864 865
				 (eq (ispell-process-status) 'run))
		    :help "Terminate Ispell subprocess"))
866
      (define-key ispell-menu-map [ispell-pdict-save]
867
	'(menu-item "Save Dictionary"
868 869
		    (lambda () (interactive) (ispell-pdict-save t t))
		    :help "Save personal dictionary"))
870 871
      (define-key ispell-menu-map [ispell-help]
	;; use (x-popup-menu last-nonmenu-event(list "" ispell-help-list)) ?
872 873 874
	'(menu-item "Help"
		    (lambda () (interactive) (describe-function 'ispell-help))
		    :help "Show standard Ispell keybindings and commands"))
875
      (define-key ispell-menu-map [ispell-complete-word]
876 877
	'(menu-item "Complete Word" ispell-complete-word
		    :help "Complete word at cursor using dictionary"))
878
      (define-key ispell-menu-map [ispell-complete-word-interior-frag]
879 880
	'(menu-item "Complete Word Fragment" ispell-complete-word-interior-frag
		    :help "Complete word fragment at cursor"))))
881

882
;;;###autoload
883 884 885
(if ispell-menu-map-needed
    (progn
      (define-key ispell-menu-map [ispell-continue]
886 887 888 889
	'(menu-item "Continue Spell-Checking" ispell-continue
		    :enable (and (boundp 'ispell-region-end)
				 (marker-position ispell-region-end)
				 (equal (marker-buffer ispell-region-end)
890 891
					(current-buffer)))
		    :help "Continue spell checking last region"))
892
      (define-key ispell-menu-map [ispell-word]
893 894
	'(menu-item "Spell-Check Word" ispell-word
		    :help "Spell-check word at cursor"))
895
      (define-key ispell-menu-map [ispell-comments-and-strings]
896 897
	'(menu-item "Spell-Check Comments" ispell-comments-and-strings
		    :help "Spell-check only comments and strings"))))
898

899
;;;###autoload
900 901
(if ispell-menu-map-needed
    (progn
902 903 904 905
      (define-key ispell-menu-map [ispell-region]
	'(menu-item "Spell-Check Region" ispell-region
		    :enable mark-active
		    :help "Spell-check text in marked region"))
906
      (define-key ispell-menu-map [ispell-message]
907 908 909
	'(menu-item "Spell-Check Message" ispell-message
		    :help "Skip headers and included message text"))
      (define-key ispell-menu-map [ispell-buffer]
910 911 912
	'(menu-item "Spell-Check Buffer" ispell-buffer
		    :help "Check spelling of selected buffer"))
      ;;(put 'ispell-region 'menu-enable 'mark-active)
913 914
      (fset 'ispell-menu-map (symbol-value 'ispell-menu-map))))

915
;;; XEmacs versions 19 & 20
916 917
(if (and xemacsp
	 (not version18p)
918 919 920
	 (featurep 'menubar)
	 (null ispell-menu-xemacs)
	 (not (and (boundp 'infodock-version) infodock-version)))
921 922 923 924 925 926 927
    (let ((dicts (cons (cons "default" nil) ispell-dictionary-alist))
	  (current-menubar (or current-menubar default-menubar))
	  (menu
	   '(["Help"		(describe-function 'ispell-help) t]
	     ;;["Help"		(popup-menu ispell-help-list)	t]
	     ["Check Message"	ispell-message			t]
	     ["Check Buffer"	ispell-buffer			t]
928
	     ["Check Comments"	ispell-comments-and-strings	t]
929 930 931 932 933 934 935
	     ["Check Word"	ispell-word			t]
	     ["Check Region"	ispell-region  (or (not zmacs-regions) (mark))]
	     ["Continue Check"	ispell-continue			t]
	     ["Complete Word Frag"ispell-complete-word-interior-frag t]
	     ["Complete Word"	ispell-complete-word		t]
	     ["Kill Process"	ispell-kill-ispell		t]
	     "-"
936 937 938 939
	     ["Save Personal Dict"(ispell-pdict-save t t)	t]
	     ["Change Dictionary" ispell-change-dictionary	t]
	     ["Select Default"  (ispell-change-dictionary "default") t]))
	  name load-dict)
940 941
      (while dicts
	(setq name (car (car dicts))
942
	      load-dict (car (cdr (member "-d" (nth 5 (car dicts)))))
943
	      dicts (cdr dicts))
944 945 946 947 948 949 950 951 952 953 954 955
	;; Include if the dictionary is in the library, or path not defined.
	(if (and (stringp name)
		 (or (not ispell-library-path)
		     (file-exists-p (concat ispell-library-path "/"
					    name ".hash"))
		     (file-exists-p (concat ispell-library-path "/"
					    name ".has"))
		     (and load-dict
			  (or (file-exists-p (concat ispell-library-path "/"
						     load-dict ".hash"))
			      (file-exists-p (concat ispell-library-path "/"
						     load-dict ".has"))))))
956 957
	    (setq menu (append menu
			       (list
958 959 960 961
				 (vector (concat "Select " (capitalize name))
					 (list 'ispell-change-dictionary name)
					 t))))))
      (setq ispell-menu-xemacs menu)
962 963 964
      (if current-menubar
	  (progn
	    (delete-menu-item '("Edit" "Spell")) ; in case already defined
965 966 967
	    (add-menu '("Edit") "Spell" ispell-menu-xemacs)))))

;;; Allow incrementing characters as integers in XEmacs 20
968
(if (and xemacsp
969 970 971 972
	 (fboundp 'int-char))
    (fset 'ispell-int-char 'int-char)
  ;; Emacs and XEmacs 19 or earlier
  (fset 'ispell-int-char 'identity))
Richard M. Stallman's avatar
Richard M. Stallman committed
973 974 975 976 977


;;; **********************************************************************


978 979 980 981 982 983 984 985 986 987
;;; This variable contains the current dictionary being used if the ispell
;;; process is running.  Otherwise it contains the global default.
(defvar ispell-dictionary nil
  "The name of the current dictionary, or nil for the default.
When `ispell-local-dictionary' is nil, `ispell-dictionary' is used to select
the dictionary for new buffers.

This is passed to the ispell process using the `-d' switch and is
used as key in `ispell-dictionary-alist' (which see).")

988
(defun ispell-decode-string (str)
989 990
  "Decodes multibyte character strings.
Protects against bogus binding of `enable-multibyte-characters' in XEmacs."
991
  (if (and (or xemacsp
992 993
	       (and (boundp 'enable-multibyte-characters)
		    enable-multibyte-characters))
994 995 996 997
	   (fboundp 'decode-coding-string)
	   (ispell-get-coding-system))
      (decode-coding-string str (ispell-get-coding-system))
    str))