diff src/abbrev.c @ 0:376386a54a3c r19-14

Import from CVS: tag r19-14
author cvs
date Mon, 13 Aug 2007 08:45:50 +0200
parents
children 859a2309aef8
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/abbrev.c	Mon Aug 13 08:45:50 2007 +0200
@@ -0,0 +1,284 @@
+/* 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, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+/* Synched up with: FSF 19.30.  Note that there are many more functions in
+   FSF's abbrev.c.  These have been moved into Lisp in XEmacs. */
+
+/* Authorship:
+
+   FSF: Original version; a long time ago.
+   JWZ or Mly: Mostly moved into Lisp; maybe 1992.
+   Ben Wing: Some changes for Mule for 19.12.
+*/
+
+/* This file has been Mule-ized. */
+
+#include <config.h>
+#include "lisp.h"
+
+#include "buffer.h"
+#include "commands.h"
+#include "insdel.h"
+#include "syntax.h"
+#include "window.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.
+Effective when explicitly called even when `abbrev-mode' is nil.
+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);
+  run_hook (Qpre_abbrev_expand_hook);
+  /* If the hook changes the buffer, treat that as having "done an
+     expansion".  */
+  value = (BUF_MODIFF (buf) != oldmodiff ? Qt : Qnil);
+
+  wordstart = 0;
+  if (!BUFFERP (Vabbrev_start_location_buffer) ||
+      XBUFFER (Vabbrev_start_location_buffer) != buf)
+    Vabbrev_start_location = Qnil;
+  if (!NILP (Vabbrev_start_location))
+    {
+      wordstart = get_buffer_pos_char (buf, Vabbrev_start_location, GB_COERCE_RANGE);
+      Vabbrev_start_location = Qnil;
+      if (wordstart < BUF_BEGV (buf) || wordstart > BUF_ZV (buf))
+        wordstart = 0;
+      if (wordstart && wordstart != BUF_ZV (buf) &&
+          BUF_FETCH_CHAR (buf, wordstart) == '-')
+	buffer_delete_range (buf, wordstart, wordstart + 1, 0);
+    }
+  if (!wordstart)
+    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 += set_charptr_emchar (p, c);
+    }
+
+  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)))
+    {
+      /* Add an undo boundary, in case we are doing this for
+         a self-inserting command which has avoided making one so far.  */
+      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))
+	  {
+	    Fupcase_initials_region (make_int (wordstart),
+				     make_int (BUF_PT (buf)),
+				     lbuf);
+	    goto caped;
+	  }
+      /* If expansion is one word, or if user says so, upcase it all. */
+      Fupcase_region (make_int (wordstart), make_int (BUF_PT (buf)),
+		      lbuf);
+    caped: ;
+    }
+  else if (uccount)
+    {
+      /* Abbrev included some caps.  Cap first initial of expansion */
+      Bufpos pos = wordstart;
+
+      /* Find the initial.  */
+      while (pos < BUF_PT (buf)
+             && !WORD_SYNTAX_P (buf->syntax_table, BUF_FETCH_CHAR (buf, pos)))
+        pos++;
+
+      /* Change just that.  */
+      Fupcase_initials_region (make_int (pos), make_int (pos + 1), lbuf);
+    }
+
+  hook = XSYMBOL (sym)->function;
+  if (!NILP (hook) && !UNBOUNDP (hook))
+    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.
+Each buffer may also have a local abbrev table.
+If it does, the local table overrides the global one
+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.
+See the function `abbrev-symbol'.
+*/ );
+
+  DEFVAR_LISP ("last-abbrev-text", &Vlast_abbrev_text /*
+The exact text of the last abbrev expanded.
+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.
+nil means use the word before point as the abbrev.
+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.
+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.
+This is the first thing that `expand-abbrev' does, and so this may change
+the current abbrev table before abbrev lookup happens.
+*/ );
+  Vpre_abbrev_expand_hook = Qnil;
+}