Move GPM check outside HAVE_X_WINDOWS.
[bpt/emacs.git] / src / abbrev.c
CommitLineData
7942b8ae 1/* Primitives for word-abbrev mode.
0b5538bd 2 Copyright (C) 1985, 1986, 1993, 1996, 1998, 2001, 2002, 2003, 2004,
4e6835db 3 2005, 2006, 2007 Free Software Foundation, Inc.
7942b8ae
RS
4
5This file is part of GNU Emacs.
6
7GNU Emacs is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
c89475dc 9the Free Software Foundation; either version 2, or (at your option)
7942b8ae
RS
10any later version.
11
12GNU Emacs is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU Emacs; see the file COPYING. If not, write to
4fc5845f
LK
19the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20Boston, MA 02110-1301, USA. */
7942b8ae
RS
21
22
18160b98 23#include <config.h>
7942b8ae 24#include <stdio.h>
7ee72033 25
7942b8ae
RS
26#include "lisp.h"
27#include "commands.h"
28#include "buffer.h"
29#include "window.h"
9192a027 30#include "charset.h"
7169beb1 31#include "syntax.h"
7942b8ae
RS
32
33/* An abbrev table is an obarray.
34 Each defined abbrev is represented by a symbol in that obarray
35 whose print name is the abbreviation.
36 The symbol's value is a string which is the expansion.
37 If its function definition is non-nil, it is called
38 after the expansion is done.
39 The plist slot of the abbrev symbol is its usage count. */
40
41/* List of all abbrev-table name symbols:
42 symbols whose values are abbrev tables. */
43
44Lisp_Object Vabbrev_table_name_list;
45
46/* The table of global abbrevs. These are in effect
47 in any buffer in which abbrev mode is turned on. */
48
49Lisp_Object Vglobal_abbrev_table;
50
51/* The local abbrev table used by default (in Fundamental Mode buffers) */
52
53Lisp_Object Vfundamental_mode_abbrev_table;
54
55/* Set nonzero when an abbrev definition is changed */
56
57int abbrevs_changed;
58
59int abbrev_all_caps;
60
61/* Non-nil => use this location as the start of abbrev to expand
62 (rather than taking the word before point as the abbrev) */
63
64Lisp_Object Vabbrev_start_location;
65
66/* Buffer that Vabbrev_start_location applies to */
67Lisp_Object Vabbrev_start_location_buffer;
68
69/* The symbol representing the abbrev most recently expanded */
70
71Lisp_Object Vlast_abbrev;
72
73/* A string for the actual text of the abbrev most recently expanded.
74 This has more info than Vlast_abbrev since case is significant. */
75
76Lisp_Object Vlast_abbrev_text;
77
78/* Character address of start of last abbrev expanded */
79
31ade731 80EMACS_INT last_abbrev_point;
7942b8ae 81
dbd7a969
RS
82/* Hook to run before expanding any abbrev. */
83
84Lisp_Object Vpre_abbrev_expand_hook, Qpre_abbrev_expand_hook;
2d6c1fc0 85
0dcd524c 86Lisp_Object Qsystem_type, Qcount, Qforce;
7942b8ae
RS
87\f
88DEFUN ("make-abbrev-table", Fmake_abbrev_table, Smake_abbrev_table, 0, 0, 0,
7ee72033
MB
89 doc: /* Create a new, empty abbrev table object. */)
90 ()
7942b8ae 91{
da2ba5c6 92 /* The value 59 is arbitrary chosen prime number. */
7942b8ae
RS
93 return Fmake_vector (make_number (59), make_number (0));
94}
95
96DEFUN ("clear-abbrev-table", Fclear_abbrev_table, Sclear_abbrev_table, 1, 1, 0,
7ee72033
MB
97 doc: /* Undefine all abbrevs in abbrev table TABLE, leaving it empty. */)
98 (table)
7942b8ae
RS
99 Lisp_Object table;
100{
101 int i, size;
102
b7826503 103 CHECK_VECTOR (table);
7942b8ae
RS
104 size = XVECTOR (table)->size;
105 abbrevs_changed = 1;
106 for (i = 0; i < size; i++)
107 XVECTOR (table)->contents[i] = make_number (0);
108 return Qnil;
109}
0dcd524c 110
2d6c1fc0 111DEFUN ("define-abbrev", Fdefine_abbrev, Sdefine_abbrev, 3, 6, 0,
7ee72033 112 doc: /* Define an abbrev in TABLE named NAME, to expand to EXPANSION and call HOOK.
8d6af892 113NAME must be a string, and should be lower-case.
b39fb64b
PJ
114EXPANSION should usually be a string.
115To undefine an abbrev, define it with EXPANSION = nil.
116If HOOK is non-nil, it should be a function of no arguments;
117it is called after EXPANSION is inserted.
118If EXPANSION is not a string, the abbrev is a special one,
119 which does not expand in the usual way but only runs HOOK.
2d6c1fc0
RS
120
121COUNT, if specified, gives the initial value for the abbrev's
122usage-count, which is incremented each time the abbrev is used.
123\(The default is zero.)
124
125SYSTEM-FLAG, if non-nil, says that this is a "system" abbreviation
0dcd524c
GM
126which should not be saved in the user's abbreviation file.
127Unless SYSTEM-FLAG is `force', a system abbreviation will not
128overwrite a non-system abbreviation of the same name. */)
2d6c1fc0
RS
129 (table, name, expansion, hook, count, system_flag)
130 Lisp_Object table, name, expansion, hook, count, system_flag;
7942b8ae
RS
131{
132 Lisp_Object sym, oexp, ohook, tem;
b7826503
PJ
133 CHECK_VECTOR (table);
134 CHECK_STRING (name);
b7734773 135
0dcd524c
GM
136 /* If defining a system abbrev, do not overwrite a non-system abbrev
137 of the same name, unless 'force is used. */
138 if (!NILP (system_flag) && !EQ (system_flag, Qforce))
139 {
140 sym = Fintern_soft (name, table);
141
142 if (!NILP (SYMBOL_VALUE (sym)) &&
143 NILP (Fplist_get (XSYMBOL (sym)->plist, Qsystem_type))) return Qnil;
144 }
145
d427b66a 146 if (NILP (count))
7942b8ae
RS
147 count = make_number (0);
148 else
b7826503 149 CHECK_NUMBER (count);
7942b8ae
RS
150
151 sym = Fintern (name, table);
152
a97569cb 153 oexp = SYMBOL_VALUE (sym);
7942b8ae
RS
154 ohook = XSYMBOL (sym)->function;
155 if (!((EQ (oexp, expansion)
09e82d7c 156 || (STRINGP (oexp) && STRINGP (expansion)
d427b66a 157 && (tem = Fstring_equal (oexp, expansion), !NILP (tem))))
7942b8ae
RS
158 &&
159 (EQ (ohook, hook)
2d6c1fc0
RS
160 || (tem = Fequal (ohook, hook), !NILP (tem))))
161 && NILP (system_flag))
7942b8ae
RS
162 abbrevs_changed = 1;
163
164 Fset (sym, expansion);
165 Ffset (sym, hook);
2d6c1fc0
RS
166
167 if (! NILP (system_flag))
168 Fsetplist (sym, list4 (Qcount, count, Qsystem_type, system_flag));
169 else
170 Fsetplist (sym, count);
7942b8ae
RS
171
172 return name;
173}
174
175DEFUN ("define-global-abbrev", Fdefine_global_abbrev, Sdefine_global_abbrev, 2, 2,
b39fb64b 176 "sDefine global abbrev: \nsExpansion for %s: ",
7ee72033
MB
177 doc: /* Define ABBREV as a global abbreviation for EXPANSION. */)
178 (abbrev, expansion)
78ce396a 179 Lisp_Object abbrev, expansion;
7942b8ae 180{
78ce396a 181 Fdefine_abbrev (Vglobal_abbrev_table, Fdowncase (abbrev),
2d6c1fc0 182 expansion, Qnil, make_number (0), Qnil);
78ce396a 183 return abbrev;
7942b8ae
RS
184}
185
186DEFUN ("define-mode-abbrev", Fdefine_mode_abbrev, Sdefine_mode_abbrev, 2, 2,
b39fb64b 187 "sDefine mode abbrev: \nsExpansion for %s: ",
7ee72033
MB
188 doc: /* Define ABBREV as a mode-specific abbreviation for EXPANSION. */)
189 (abbrev, expansion)
78ce396a 190 Lisp_Object abbrev, expansion;
7942b8ae 191{
d427b66a 192 if (NILP (current_buffer->abbrev_table))
7942b8ae
RS
193 error ("Major mode has no abbrev table");
194
78ce396a 195 Fdefine_abbrev (current_buffer->abbrev_table, Fdowncase (abbrev),
2d6c1fc0 196 expansion, Qnil, make_number (0), Qnil);
78ce396a 197 return abbrev;
7942b8ae
RS
198}
199
200DEFUN ("abbrev-symbol", Fabbrev_symbol, Sabbrev_symbol, 1, 2, 0,
7ee72033 201 doc: /* Return the symbol representing abbrev named ABBREV.
b39fb64b
PJ
202This symbol's name is ABBREV, but it is not the canonical symbol of that name;
203it is interned in an abbrev-table rather than the normal obarray.
204The value is nil if that abbrev is not defined.
205Optional second arg TABLE is abbrev table to look it up in.
7ee72033
MB
206The default is to try buffer's mode-specific abbrev table, then global table. */)
207 (abbrev, table)
7942b8ae
RS
208 Lisp_Object abbrev, table;
209{
210 Lisp_Object sym;
b7826503 211 CHECK_STRING (abbrev);
d427b66a 212 if (!NILP (table))
7942b8ae
RS
213 sym = Fintern_soft (abbrev, table);
214 else
215 {
216 sym = Qnil;
d427b66a 217 if (!NILP (current_buffer->abbrev_table))
7942b8ae 218 sym = Fintern_soft (abbrev, current_buffer->abbrev_table);
a97569cb 219 if (NILP (SYMBOL_VALUE (sym)))
7942b8ae 220 sym = Qnil;
d427b66a 221 if (NILP (sym))
7942b8ae
RS
222 sym = Fintern_soft (abbrev, Vglobal_abbrev_table);
223 }
a97569cb
GM
224 if (NILP (SYMBOL_VALUE (sym)))
225 return Qnil;
7942b8ae
RS
226 return sym;
227}
228
229DEFUN ("abbrev-expansion", Fabbrev_expansion, Sabbrev_expansion, 1, 2, 0,
7ee72033 230 doc: /* Return the string that ABBREV expands into in the current buffer.
b39fb64b 231Optionally specify an abbrev table as second arg;
7ee72033
MB
232then ABBREV is looked up in that table only. */)
233 (abbrev, table)
7942b8ae
RS
234 Lisp_Object abbrev, table;
235{
236 Lisp_Object sym;
237 sym = Fabbrev_symbol (abbrev, table);
d427b66a 238 if (NILP (sym)) return sym;
7942b8ae
RS
239 return Fsymbol_value (sym);
240}
241\f
242/* Expand the word before point, if it is an abbrev.
243 Returns 1 if an expansion is done. */
244
245DEFUN ("expand-abbrev", Fexpand_abbrev, Sexpand_abbrev, 0, 0, "",
7ee72033 246 doc: /* Expand the abbrev before point, if there is an abbrev there.
b39fb64b 247Effective when explicitly called even when `abbrev-mode' is nil.
7ee72033
MB
248Returns the abbrev symbol, if expansion took place. */)
249 ()
7942b8ae
RS
250{
251 register char *buffer, *p;
aa406bac 252 int wordstart, wordend;
530e0751 253 register int wordstart_byte, wordend_byte, idx, idx_byte;
7942b8ae
RS
254 int whitecnt;
255 int uccount = 0, lccount = 0;
256 register Lisp_Object sym;
257 Lisp_Object expansion, hook, tem;
ba70da8f 258 Lisp_Object value;
530e0751 259 int multibyte = ! NILP (current_buffer->enable_multibyte_characters);
7942b8ae 260
f530ce27
RS
261 value = Qnil;
262
451eaa21
RS
263 Frun_hooks (1, &Qpre_abbrev_expand_hook);
264
dc7e2b30 265 wordstart = 0;
f530ce27
RS
266 if (!(BUFFERP (Vabbrev_start_location_buffer)
267 && XBUFFER (Vabbrev_start_location_buffer) == current_buffer))
7942b8ae 268 Vabbrev_start_location = Qnil;
d427b66a 269 if (!NILP (Vabbrev_start_location))
7942b8ae
RS
270 {
271 tem = Vabbrev_start_location;
b7826503 272 CHECK_NUMBER_COERCE_MARKER (tem);
7942b8ae
RS
273 wordstart = XINT (tem);
274 Vabbrev_start_location = Qnil;
dc7e2b30
KH
275 if (wordstart < BEGV || wordstart > ZV)
276 wordstart = 0;
aa406bac
RS
277 if (wordstart && wordstart != ZV)
278 {
279 wordstart_byte = CHAR_TO_BYTE (wordstart);
280 if (FETCH_BYTE (wordstart_byte) == '-')
281 del_range (wordstart, wordstart + 1);
282 }
7942b8ae 283 }
dc7e2b30 284 if (!wordstart)
6ec8bbd2 285 wordstart = scan_words (PT, -1);
7942b8ae
RS
286
287 if (!wordstart)
ba70da8f 288 return value;
7942b8ae 289
aa406bac 290 wordstart_byte = CHAR_TO_BYTE (wordstart);
7942b8ae
RS
291 wordend = scan_words (wordstart, 1);
292 if (!wordend)
ba70da8f 293 return value;
7942b8ae 294
6ec8bbd2
KH
295 if (wordend > PT)
296 wordend = PT;
aa406bac
RS
297
298 wordend_byte = CHAR_TO_BYTE (wordend);
6ec8bbd2 299 whitecnt = PT - wordend;
7942b8ae 300 if (wordend <= wordstart)
ba70da8f 301 return value;
7942b8ae 302
aa406bac 303 p = buffer = (char *) alloca (wordend_byte - wordstart_byte);
7942b8ae 304
530e0751 305 for (idx = wordstart, idx_byte = wordstart_byte; idx < wordend; )
7942b8ae 306 {
530e0751
KH
307 register int c;
308
309 if (multibyte)
310 {
311 FETCH_CHAR_ADVANCE (c, idx, idx_byte);
312 }
313 else
314 {
315 c = FETCH_BYTE (idx_byte);
316 idx++, idx_byte++;
317 }
177c0ea7 318
7942b8ae
RS
319 if (UPPERCASEP (c))
320 c = DOWNCASE (c), uccount++;
321 else if (! NOCASEP (c))
322 lccount++;
530e0751
KH
323 if (multibyte)
324 p += CHAR_STRING (c, p);
325 else
326 *p++ = c;
7942b8ae
RS
327 }
328
09e82d7c 329 if (VECTORP (current_buffer->abbrev_table))
fc412686 330 sym = oblookup (current_buffer->abbrev_table, buffer,
530e0751 331 wordend - wordstart, p - buffer);
7942b8ae 332 else
2a43e2bc 333 XSETFASTINT (sym, 0);
2d6c1fc0 334
a97569cb 335 if (INTEGERP (sym) || NILP (SYMBOL_VALUE (sym)))
fc412686 336 sym = oblookup (Vglobal_abbrev_table, buffer,
530e0751 337 wordend - wordstart, p - buffer);
a97569cb 338 if (INTEGERP (sym) || NILP (SYMBOL_VALUE (sym)))
ba70da8f 339 return value;
7942b8ae
RS
340
341 if (INTERACTIVE && !EQ (minibuf_window, selected_window))
342 {
aba686ed
RS
343 /* Add an undo boundary, in case we are doing this for
344 a self-inserting command which has avoided making one so far. */
7942b8ae
RS
345 SET_PT (wordend);
346 Fundo_boundary ();
347 }
b7734773 348
7942b8ae
RS
349 Vlast_abbrev_text
350 = Fbuffer_substring (make_number (wordstart), make_number (wordend));
7942b8ae 351
b7734773 352 /* Now sym is the abbrev symbol. */
7942b8ae 353 Vlast_abbrev = sym;
f530ce27 354 value = sym;
7942b8ae
RS
355 last_abbrev_point = wordstart;
356
2d6c1fc0 357 /* Increment use count. */
09e82d7c 358 if (INTEGERP (XSYMBOL (sym)->plist))
7942b8ae 359 XSETINT (XSYMBOL (sym)->plist,
2d6c1fc0 360 XINT (XSYMBOL (sym)->plist) + 1);
8d320872 361 else if (INTEGERP (tem = Fget (sym, Qcount)))
2d6c1fc0 362 Fput (sym, Qcount, make_number (XINT (tem) + 1));
7942b8ae 363
b7734773
RS
364 /* If this abbrev has an expansion, delete the abbrev
365 and insert the expansion. */
a97569cb 366 expansion = SYMBOL_VALUE (sym);
b7734773 367 if (STRINGP (expansion))
7942b8ae 368 {
b7734773
RS
369 SET_PT (wordstart);
370
d5db4077
KR
371 insert_from_string (expansion, 0, 0, SCHARS (expansion),
372 SBYTES (expansion), 1);
f8f096e9
RS
373 del_range_both (PT, PT_BYTE,
374 wordend + (PT - wordstart),
375 wordend_byte + (PT_BYTE - wordstart_byte),
376 1);
377
b7734773
RS
378 SET_PT (PT + whitecnt);
379
380 if (uccount && !lccount)
381 {
382 /* Abbrev was all caps */
383 /* If expansion is multiple words, normally capitalize each word */
384 /* This used to be if (!... && ... >= ...) Fcapitalize; else Fupcase
385 but Megatest 68000 compiler can't handle that */
386 if (!abbrev_all_caps)
387 if (scan_words (PT, -1) > scan_words (wordstart, 1))
388 {
389 Fupcase_initials_region (make_number (wordstart),
390 make_number (PT));
391 goto caped;
392 }
393 /* If expansion is one word, or if user says so, upcase it all. */
394 Fupcase_region (make_number (wordstart), make_number (PT));
395 caped: ;
396 }
397 else if (uccount)
398 {
399 /* Abbrev included some caps. Cap first initial of expansion */
aa406bac 400 int pos = wordstart_byte;
b7734773
RS
401
402 /* Find the initial. */
aa406bac
RS
403 while (pos < PT_BYTE
404 && SYNTAX (*BUF_BYTE_ADDRESS (current_buffer, pos)) != Sword)
b7734773
RS
405 pos++;
406
407 /* Change just that. */
aa406bac 408 pos = BYTE_TO_CHAR (pos);
b7734773
RS
409 Fupcase_initials_region (make_number (pos), make_number (pos + 1));
410 }
7942b8ae
RS
411 }
412
413 hook = XSYMBOL (sym)->function;
d427b66a 414 if (!NILP (hook))
79d2af9c
GM
415 {
416 Lisp_Object expanded, prop;
417
c87dbfd0 418 /* If the abbrev has a hook function, run it. */
79d2af9c 419 expanded = call0 (hook);
c87dbfd0 420
ca70e62f
PJ
421 /* In addition, if the hook function is a symbol with
422 a non-nil `no-self-insert' property, let the value it returned
c87dbfd0
RS
423 specify whether we consider that an expansion took place. If
424 it returns nil, no expansion has been done. */
425
79d2af9c
GM
426 if (SYMBOLP (hook)
427 && NILP (expanded)
428 && (prop = Fget (hook, intern ("no-self-insert")),
429 !NILP (prop)))
430 value = Qnil;
431 }
7942b8ae 432
f530ce27 433 return value;
7942b8ae
RS
434}
435
436DEFUN ("unexpand-abbrev", Funexpand_abbrev, Sunexpand_abbrev, 0, 0, "",
7ee72033 437 doc: /* Undo the expansion of the last abbrev that expanded.
b39fb64b 438This differs from ordinary undo in that other editing done since then
7ee72033
MB
439is not undone. */)
440 ()
7942b8ae 441{
6ec8bbd2 442 int opoint = PT;
7942b8ae
RS
443 int adjust = 0;
444 if (last_abbrev_point < BEGV
445 || last_abbrev_point > ZV)
446 return Qnil;
447 SET_PT (last_abbrev_point);
09e82d7c 448 if (STRINGP (Vlast_abbrev_text))
7942b8ae
RS
449 {
450 /* This isn't correct if Vlast_abbrev->function was used
451 to do the expansion */
452 Lisp_Object val;
aa406bac
RS
453 int zv_before;
454
a97569cb 455 val = SYMBOL_VALUE (Vlast_abbrev);
09e82d7c 456 if (!STRINGP (val))
d4db983a 457 error ("Value of `abbrev-symbol' must be a string");
aa406bac 458 zv_before = ZV;
d5db4077 459 del_range_byte (PT_BYTE, PT_BYTE + SBYTES (val), 1);
0c287112 460 /* Don't inherit properties here; just copy from old contents. */
fc412686 461 insert_from_string (Vlast_abbrev_text, 0, 0,
d5db4077
KR
462 SCHARS (Vlast_abbrev_text),
463 SBYTES (Vlast_abbrev_text), 0);
7942b8ae 464 Vlast_abbrev_text = Qnil;
aa406bac
RS
465 /* Total number of characters deleted. */
466 adjust = ZV - zv_before;
7942b8ae 467 }
57522629 468 SET_PT (last_abbrev_point < opoint ? opoint + adjust : opoint);
7942b8ae
RS
469 return Qnil;
470}
471\f
aa406bac 472static void
7942b8ae
RS
473write_abbrev (sym, stream)
474 Lisp_Object sym, stream;
475{
2d6c1fc0
RS
476 Lisp_Object name, count, system_flag;
477
478 if (INTEGERP (XSYMBOL (sym)->plist))
479 {
480 count = XSYMBOL (sym)->plist;
481 system_flag = Qnil;
482 }
483 else
484 {
485 count = Fget (sym, Qcount);
486 system_flag = Fget (sym, Qsystem_type);
487 }
488
489 if (NILP (SYMBOL_VALUE (sym)) || ! NILP (system_flag))
7942b8ae 490 return;
2d6c1fc0 491
7942b8ae 492 insert (" (", 5);
caeead20 493 name = SYMBOL_NAME (sym);
7942b8ae
RS
494 Fprin1 (name, stream);
495 insert (" ", 1);
a97569cb 496 Fprin1 (SYMBOL_VALUE (sym), stream);
7942b8ae
RS
497 insert (" ", 1);
498 Fprin1 (XSYMBOL (sym)->function, stream);
499 insert (" ", 1);
2d6c1fc0 500 Fprin1 (count, stream);
7942b8ae
RS
501 insert (")\n", 2);
502}
503
aa406bac 504static void
7942b8ae
RS
505describe_abbrev (sym, stream)
506 Lisp_Object sym, stream;
507{
2d6c1fc0
RS
508 Lisp_Object one, count, system_flag;
509
510 if (INTEGERP (XSYMBOL (sym)->plist))
511 {
512 count = XSYMBOL (sym)->plist;
513 system_flag = Qnil;
514 }
515 else
516 {
517 count = Fget (sym, Qcount);
518 system_flag = Fget (sym, Qsystem_type);
519 }
7942b8ae 520
a97569cb 521 if (NILP (SYMBOL_VALUE (sym)))
7942b8ae 522 return;
2d6c1fc0 523
7942b8ae
RS
524 one = make_number (1);
525 Fprin1 (Fsymbol_name (sym), stream);
2d6c1fc0
RS
526
527 if (!NILP (system_flag))
528 {
529 insert_string (" (sys)");
530 Findent_to (make_number (20), one);
531 }
532 else
533 Findent_to (make_number (15), one);
534
535 Fprin1 (count, stream);
7942b8ae 536 Findent_to (make_number (20), one);
a97569cb 537 Fprin1 (SYMBOL_VALUE (sym), stream);
d427b66a 538 if (!NILP (XSYMBOL (sym)->function))
7942b8ae
RS
539 {
540 Findent_to (make_number (45), one);
541 Fprin1 (XSYMBOL (sym)->function, stream);
542 }
543 Fterpri (stream);
544}
545
d06d657c
RS
546static void
547record_symbol (sym, list)
548 Lisp_Object sym, list;
549{
550 XSETCDR (list, Fcons (sym, XCDR (list)));
551}
552
a0d76c27 553DEFUN ("insert-abbrev-table-description", Finsert_abbrev_table_description,
03be2694 554 Sinsert_abbrev_table_description, 1, 2, 0,
7ee72033 555 doc: /* Insert before point a full description of abbrev table named NAME.
b39fb64b
PJ
556NAME is a symbol whose value is an abbrev table.
557If optional 2nd arg READABLE is non-nil, a human-readable description
558is inserted. Otherwise the description is an expression,
559a call to `define-abbrev-table', which would
2d6c1fc0
RS
560define the abbrev table NAME exactly as it is currently defined.
561
7f144ff5
LT
562Abbrevs marked as "system abbrevs" are normally omitted. However, if
563READABLE is non-nil, they are listed. */)
7ee72033 564 (name, readable)
7942b8ae
RS
565 Lisp_Object name, readable;
566{
567 Lisp_Object table;
d06d657c 568 Lisp_Object symbols;
7942b8ae
RS
569 Lisp_Object stream;
570
b7826503 571 CHECK_SYMBOL (name);
7942b8ae 572 table = Fsymbol_value (name);
b7826503 573 CHECK_VECTOR (table);
7942b8ae 574
6520d056 575 XSETBUFFER (stream, current_buffer);
7942b8ae 576
d06d657c
RS
577 symbols = Fcons (Qnil, Qnil);
578 map_obarray (table, record_symbol, symbols);
579 symbols = XCDR (symbols);
580 symbols = Fsort (symbols, Qstring_lessp);
581
d427b66a 582 if (!NILP (readable))
7942b8ae
RS
583 {
584 insert_string ("(");
585 Fprin1 (name, stream);
586 insert_string (")\n\n");
d06d657c
RS
587 while (! NILP (symbols))
588 {
589 describe_abbrev (XCAR (symbols), stream);
590 symbols = XCDR (symbols);
591 }
592
7942b8ae
RS
593 insert_string ("\n\n");
594 }
595 else
596 {
597 insert_string ("(define-abbrev-table '");
598 Fprin1 (name, stream);
599 insert_string (" '(\n");
d06d657c
RS
600 while (! NILP (symbols))
601 {
602 write_abbrev (XCAR (symbols), stream);
603 symbols = XCDR (symbols);
604 }
7942b8ae
RS
605 insert_string (" ))\n\n");
606 }
607
608 return Qnil;
609}
610\f
611DEFUN ("define-abbrev-table", Fdefine_abbrev_table, Sdefine_abbrev_table,
612 2, 2, 0,
7ee72033 613 doc: /* Define TABLENAME (a symbol) as an abbrev table name.
b39fb64b 614Define abbrevs in it according to DEFINITIONS, which is a list of elements
2d6c1fc0
RS
615of the form (ABBREVNAME EXPANSION HOOK USECOUNT SYSTEMFLAG).
616\(If the list is shorter than that, omitted elements default to nil). */)
7ee72033 617 (tablename, definitions)
b9d613cc 618 Lisp_Object tablename, definitions;
7942b8ae
RS
619{
620 Lisp_Object name, exp, hook, count;
2d6c1fc0 621 Lisp_Object table, elt, sys;
7942b8ae 622
b7826503 623 CHECK_SYMBOL (tablename);
78ce396a
EN
624 table = Fboundp (tablename);
625 if (NILP (table) || (table = Fsymbol_value (tablename), NILP (table)))
7942b8ae
RS
626 {
627 table = Fmake_abbrev_table ();
78ce396a 628 Fset (tablename, table);
b9d613cc 629 Vabbrev_table_name_list = Fcons (tablename, Vabbrev_table_name_list);
7942b8ae 630 }
b7826503 631 CHECK_VECTOR (table);
7942b8ae 632
52ad5ecc 633 for (; CONSP (definitions); definitions = XCDR (definitions))
7942b8ae 634 {
52ad5ecc 635 elt = XCAR (definitions);
0292bcb1
JB
636 name = Fcar (elt); elt = Fcdr (elt);
637 exp = Fcar (elt); elt = Fcdr (elt);
638 hook = Fcar (elt); elt = Fcdr (elt);
2d6c1fc0
RS
639 count = Fcar (elt); elt = Fcdr (elt);
640 sys = Fcar (elt);
641 Fdefine_abbrev (table, name, exp, hook, count, sys);
7942b8ae
RS
642 }
643 return Qnil;
644}
645\f
dfcf069d 646void
7942b8ae
RS
647syms_of_abbrev ()
648{
2d6c1fc0
RS
649 Qsystem_type = intern ("system-type");
650 staticpro (&Qsystem_type);
651
652 Qcount = intern ("count");
653 staticpro (&Qcount);
654
0dcd524c
GM
655 Qforce = intern ("force");
656 staticpro (&Qforce);
657
7ee72033
MB
658 DEFVAR_LISP ("abbrev-table-name-list", &Vabbrev_table_name_list,
659 doc: /* List of symbols whose values are abbrev tables. */);
7942b8ae
RS
660 Vabbrev_table_name_list = Fcons (intern ("fundamental-mode-abbrev-table"),
661 Fcons (intern ("global-abbrev-table"),
662 Qnil));
663
7ee72033
MB
664 DEFVAR_LISP ("global-abbrev-table", &Vglobal_abbrev_table,
665 doc: /* The abbrev table whose abbrevs affect all buffers.
b39fb64b
PJ
666Each buffer may also have a local abbrev table.
667If it does, the local table overrides the global one
668for any particular abbrev defined in both. */);
7942b8ae
RS
669 Vglobal_abbrev_table = Fmake_abbrev_table ();
670
7ee72033
MB
671 DEFVAR_LISP ("fundamental-mode-abbrev-table", &Vfundamental_mode_abbrev_table,
672 doc: /* The abbrev table of mode-specific abbrevs for Fundamental Mode. */);
7942b8ae
RS
673 Vfundamental_mode_abbrev_table = Fmake_abbrev_table ();
674 current_buffer->abbrev_table = Vfundamental_mode_abbrev_table;
c8bb8167 675 buffer_defaults.abbrev_table = Vfundamental_mode_abbrev_table;
7942b8ae 676
7ee72033
MB
677 DEFVAR_LISP ("last-abbrev", &Vlast_abbrev,
678 doc: /* The abbrev-symbol of the last abbrev expanded. See `abbrev-symbol'. */);
7942b8ae 679
7ee72033
MB
680 DEFVAR_LISP ("last-abbrev-text", &Vlast_abbrev_text,
681 doc: /* The exact text of the last abbrev expanded.
7ceb2122 682A value of nil means the abbrev has already been unexpanded. */);
7942b8ae 683
7ee72033
MB
684 DEFVAR_INT ("last-abbrev-location", &last_abbrev_point,
685 doc: /* The location of the start of the last abbrev expanded. */);
7942b8ae
RS
686
687 Vlast_abbrev = Qnil;
688 Vlast_abbrev_text = Qnil;
689 last_abbrev_point = 0;
690
7ee72033
MB
691 DEFVAR_LISP ("abbrev-start-location", &Vabbrev_start_location,
692 doc: /* Buffer position for `expand-abbrev' to use as the start of the abbrev.
ca70e62f 693When nil, use the word before point as the abbrev.
b39fb64b 694Calling `expand-abbrev' sets this to nil. */);
7942b8ae
RS
695 Vabbrev_start_location = Qnil;
696
7ee72033
MB
697 DEFVAR_LISP ("abbrev-start-location-buffer", &Vabbrev_start_location_buffer,
698 doc: /* Buffer that `abbrev-start-location' has been set for.
b39fb64b 699Trying to expand an abbrev in any other buffer clears `abbrev-start-location'. */);
7942b8ae
RS
700 Vabbrev_start_location_buffer = Qnil;
701
7ee72033
MB
702 DEFVAR_PER_BUFFER ("local-abbrev-table", &current_buffer->abbrev_table, Qnil,
703 doc: /* Local (mode-specific) abbrev table of current buffer. */);
7942b8ae 704
7ee72033
MB
705 DEFVAR_BOOL ("abbrevs-changed", &abbrevs_changed,
706 doc: /* Set non-nil by defining or altering any word abbrevs.
b39fb64b 707This causes `save-some-buffers' to offer to save the abbrevs. */);
7942b8ae
RS
708 abbrevs_changed = 0;
709
7ee72033
MB
710 DEFVAR_BOOL ("abbrev-all-caps", &abbrev_all_caps,
711 doc: /* *Set non-nil means expand multi-word abbrevs all caps if abbrev was so. */);
7942b8ae
RS
712 abbrev_all_caps = 0;
713
7ee72033
MB
714 DEFVAR_LISP ("pre-abbrev-expand-hook", &Vpre_abbrev_expand_hook,
715 doc: /* Function or functions to be called before abbrev expansion is done.
b39fb64b
PJ
716This is the first thing that `expand-abbrev' does, and so this may change
717the current abbrev table before abbrev lookup happens. */);
dbd7a969
RS
718 Vpre_abbrev_expand_hook = Qnil;
719 Qpre_abbrev_expand_hook = intern ("pre-abbrev-expand-hook");
720 staticpro (&Qpre_abbrev_expand_hook);
721
7942b8ae
RS
722 defsubr (&Smake_abbrev_table);
723 defsubr (&Sclear_abbrev_table);
724 defsubr (&Sdefine_abbrev);
725 defsubr (&Sdefine_global_abbrev);
726 defsubr (&Sdefine_mode_abbrev);
727 defsubr (&Sabbrev_expansion);
728 defsubr (&Sabbrev_symbol);
729 defsubr (&Sexpand_abbrev);
730 defsubr (&Sunexpand_abbrev);
731 defsubr (&Sinsert_abbrev_table_description);
732 defsubr (&Sdefine_abbrev_table);
733}
ab5796a9
MB
734
735/* arch-tag: b721db69-f633-44a8-a361-c275acbdad7d
736 (do not change this comment) */