This is abbrev.c in view mode; [Download] [Up]
/* Primitives for word-abbrev mode.
Copyright (C) 1985, 1986, 1992, 1993 Free Software Foundation, Inc.
This file is part of XEmacs.
XEmacs 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.
XEmacs 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 XEmacs; see the file COPYING. If not, write to the Free
Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Synched up with: FSF 19.28. Note that there are many more functions in
FSF's abbrev.c. These have been moved into Lisp in XEmacs. */
/* This file has been Mule-ized. */
#include <config.h>
#include "lisp.h"
#include "commands.h"
#include "buffer.h"
#include "window.h"
#include "insdel.h"
/* An abbrev table is an obarray.
Each defined abbrev is represented by a symbol in that obarray
whose print name is the abbreviation.
The symbol's value is a string which is the expansion.
If its function definition is non-nil, it is called
after the expansion is done.
The plist slot of the abbrev symbol is its usage count. */
/* The table of global abbrevs. These are in effect
in any buffer in which abbrev mode is turned on. */
Lisp_Object Vglobal_abbrev_table;
int abbrev_all_caps;
/* Non-nil => use this location as the start of abbrev to expand
(rather than taking the word before point as the abbrev) */
Lisp_Object Vabbrev_start_location;
/* Buffer that Vabbrev_start_location applies to */
Lisp_Object Vabbrev_start_location_buffer;
/* The symbol representing the abbrev most recently expanded */
Lisp_Object Vlast_abbrev;
/* A string for the actual text of the abbrev most recently expanded.
This has more info than Vlast_abbrev since case is significant. */
Lisp_Object Vlast_abbrev_text;
/* Character address of start of last abbrev expanded */
int last_abbrev_point;
/* Hook to run before expanding any abbrev. */
Lisp_Object Vpre_abbrev_expand_hook, Qpre_abbrev_expand_hook;
/* Expand the word before point, if it is an abbrev.
Returns Qt if an expansion is done. */
DEFUN ("expand-abbrev", Fexpand_abbrev, Sexpand_abbrev, 0, 0, "",
"Expand the abbrev before point, if there is an abbrev there.\n\
Effective when explicitly called even when `abbrev-mode' is nil.\n\
Returns t if expansion took place.")
()
{
/* This function can GC */
REGISTER Bufbyte *buffer, *p;
REGISTER Bufpos wordstart, wordend, idx;
Charcount whitecnt;
Charcount uccount = 0, lccount = 0;
REGISTER Lisp_Object sym;
Lisp_Object expansion, hook, value;
struct buffer *buf = current_buffer;
Lisp_Object lbuf;
int oldmodiff = BUF_MODIFF (buf);
XSETBUFFER (lbuf, buf);
if (!NILP (Vrun_hooks))
call1 (Vrun_hooks, Qpre_abbrev_expand_hook);
/* If the hook changes the buffer, treat that as having "done an
expansion". */
value = (BUF_MODIFF (buf) != oldmodiff ? Qt : Qnil);
if (!BUFFERP (Vabbrev_start_location_buffer) ||
XBUFFER (Vabbrev_start_location_buffer) != buf)
Vabbrev_start_location = Qnil;
if (!NILP (Vabbrev_start_location))
{
wordstart = get_bufpos (buf, Vabbrev_start_location, GB_COERCE_RANGE);
Vabbrev_start_location = Qnil;
if (BUF_FETCH_CHAR (buf, wordstart) == '-')
buffer_delete_range (buf, wordstart, wordstart + 1, 0);
}
else
wordstart = scan_words (buf, BUF_PT (buf), -1);
if (!wordstart)
return value;
wordend = scan_words (buf, wordstart, 1);
if (!wordend)
return value;
if (wordend > BUF_PT (buf))
wordend = BUF_PT (buf);
whitecnt = BUF_PT (buf) - wordend;
if (wordend <= wordstart)
return value;
p = buffer = (Bufbyte *) alloca (MAX_EMCHAR_LEN*(wordend - wordstart));
for (idx = wordstart; idx < wordend; idx++)
{
REGISTER Emchar c = BUF_FETCH_CHAR (buf, idx);
if (UPPERCASEP (buf, c))
c = DOWNCASE (buf, c), uccount++;
else if (! NOCASEP (buf, c))
lccount++;
p += emchar_to_charptr (c, p);
}
if (VECTORP (buf->abbrev_table))
sym = oblookup (buf->abbrev_table,
buffer,
p - buffer);
else
sym = Qzero;
if (INTP (sym) || NILP (XSYMBOL (sym)->value))
sym = oblookup (Vglobal_abbrev_table,
buffer,
p - buffer);
if (INTP (sym) || NILP (XSYMBOL (sym)->value))
return value;
if (INTERACTIVE && !EQ (minibuf_window, Fselected_window (Qnil)))
{
BUF_SET_PT (buf, wordend);
Fundo_boundary ();
}
BUF_SET_PT (buf, wordstart);
Vlast_abbrev_text =
make_string_from_buffer (buf, wordstart, wordend - wordstart);
buffer_delete_range (buf, wordstart, wordend, 0);
/* Now sym is the abbrev symbol. */
Vlast_abbrev = sym;
last_abbrev_point = wordstart;
if (INTP (XSYMBOL (sym)->plist))
XSETINT (XSYMBOL (sym)->plist,
XINT (XSYMBOL (sym)->plist) + 1); /* Increment use count */
expansion = XSYMBOL (sym)->value;
buffer_insert_lisp_string (buf, expansion);
BUF_SET_PT (buf, BUF_PT (buf) + whitecnt);
if (uccount && !lccount)
{
/* Abbrev was all caps */
/* If expansion is multiple words, normally capitalize each word */
/* This used to be if (!... && ... >= ...) Fcapitalize; else Fupcase
but Megatest 68000 compiler can't handle that */
if (!abbrev_all_caps)
if (scan_words (buf, BUF_PT (buf), -1) >
scan_words (buf, wordstart, 1))
{
upcase_initials_region (buf, make_number (wordstart),
make_number (BUF_PT (buf)));
goto caped;
}
/* If expansion is one word, or if user says so, upcase it all. */
Fupcase_region (make_number (wordstart), make_number (BUF_PT (buf)),
lbuf);
caped: ;
}
else if (uccount)
{
/* Abbrev included some caps. Cap first initial of expansion */
int speccount = specpdl_depth ();
Bufpos old_pt = BUF_PT (buf);
/* Don't let Fcapitalize_word operate on text after point. */
record_unwind_protect (save_restriction_restore,
save_restriction_save ());
Fnarrow_to_region (make_number (BUF_BEGV (buf)),
make_number (BUF_PT (buf)), lbuf);
BUF_SET_PT (buf, wordstart);
Fcapitalize_word (make_number (1), lbuf);
BUF_SET_PT (buf, old_pt);
unbind_to (speccount, Qnil);
}
hook = XSYMBOL (sym)->function;
if (!NILP (hook) && !EQ (hook, Qunbound))
call0 (hook);
return Qt;
}
void
syms_of_abbrev (void)
{
defsymbol (&Qpre_abbrev_expand_hook, "pre-abbrev-expand-hook");
defsubr (&Sexpand_abbrev);
}
void
vars_of_abbrev (void)
{
DEFVAR_LISP ("global-abbrev-table", &Vglobal_abbrev_table,
"The abbrev table whose abbrevs affect all buffers.\n\
Each buffer may also have a local abbrev table.\n\
If it does, the local table overrides the global one\n\
for any particular abbrev defined in both.");
Vglobal_abbrev_table = Qnil; /* setup by Lisp code */
DEFVAR_LISP ("last-abbrev", &Vlast_abbrev,
"The abbrev-symbol of the last abbrev expanded.\n\
See the function `abbrev-symbol'.");
DEFVAR_LISP ("last-abbrev-text", &Vlast_abbrev_text,
"The exact text of the last abbrev expanded.\n\
nil if the abbrev has already been unexpanded.");
DEFVAR_INT ("last-abbrev-location", &last_abbrev_point,
"The location of the start of the last abbrev expanded.");
Vlast_abbrev = Qnil;
Vlast_abbrev_text = Qnil;
last_abbrev_point = 0;
DEFVAR_LISP ("abbrev-start-location", &Vabbrev_start_location,
"Buffer position for `expand-abbrev' to use as the start of the abbrev.\n\
nil means use the word before point as the abbrev.\n\
Calling `expand-abbrev' sets this to nil.");
Vabbrev_start_location = Qnil;
DEFVAR_LISP ("abbrev-start-location-buffer", &Vabbrev_start_location_buffer,
"Buffer that `abbrev-start-location' has been set for.\n\
Trying to expand an abbrev in any other buffer clears `abbrev-start-location'.");
Vabbrev_start_location_buffer = Qnil;
DEFVAR_BOOL ("abbrev-all-caps", &abbrev_all_caps,
"*Set non-nil means expand multi-word abbrevs all caps if abbrev was so.");
abbrev_all_caps = 0;
DEFVAR_LISP ("pre-abbrev-expand-hook", &Vpre_abbrev_expand_hook,
"Function or functions to be called before abbrev expansion is done.\n\
This is the first thing that `expand-abbrev' does, and so this may change\n\
the current abbrev table before abbrev lookup happens.");
Vpre_abbrev_expand_hook = Qnil;
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.