annotate src/abbrev.c @ 665:fdefd0186b75

[xemacs-hg @ 2001-09-20 06:28:42 by ben] The great integral types renaming. The purpose of this is to rationalize the names used for various integral types, so that they match their intended uses and follow consist conventions, and eliminate types that were not semantically different from each other. The conventions are: -- All integral types that measure quantities of anything are signed. Some people disagree vociferously with this, but their arguments are mostly theoretical, and are vastly outweighed by the practical headaches of mixing signed and unsigned values, and more importantly by the far increased likelihood of inadvertent bugs: Because of the broken "viral" nature of unsigned quantities in C (operations involving mixed signed/unsigned are done unsigned, when exactly the opposite is nearly always wanted), even a single error in declaring a quantity unsigned that should be signed, or even the even more subtle error of comparing signed and unsigned values and forgetting the necessary cast, can be catastrophic, as comparisons will yield wrong results. -Wsign-compare is turned on specifically to catch this, but this tends to result in a great number of warnings when mixing signed and unsigned, and the casts are annoying. More has been written on this elsewhere. -- All such quantity types just mentioned boil down to EMACS_INT, which is 32 bits on 32-bit machines and 64 bits on 64-bit machines. This is guaranteed to be the same size as Lisp objects of type `int', and (as far as I can tell) of size_t (unsigned!) and ssize_t. The only type below that is not an EMACS_INT is Hashcode, which is an unsigned value of the same size as EMACS_INT. -- Type names should be relatively short (no more than 10 characters or so), with the first letter capitalized and no underscores if they can at all be avoided. -- "count" == a zero-based measurement of some quantity. Includes sizes, offsets, and indexes. -- "bpos" == a one-based measurement of a position in a buffer. "Charbpos" and "Bytebpos" count text in the buffer, rather than bytes in memory; thus Bytebpos does not directly correspond to the memory representation. Use "Membpos" for this. -- "Char" refers to internal-format characters, not to the C type "char", which is really a byte. -- For the actual name changes, see the script below. I ran the following script to do the conversion. (NOTE: This script is idempotent. You can safely run it multiple times and it will not screw up previous results -- in fact, it will do nothing if nothing has changed. Thus, it can be run repeatedly as necessary to handle patches coming in from old workspaces, or old branches.) There are two tags, just before and just after the change: `pre-integral-type-rename' and `post-integral-type-rename'. When merging code from the main trunk into a branch, the best thing to do is first merge up to `pre-integral-type-rename', then apply the script and associated changes, then merge from `post-integral-type-change' to the present. (Alternatively, just do the merging in one operation; but you may then have a lot of conflicts needing to be resolved by hand.) Script `fixtypes.sh' follows: ----------------------------------- cut ------------------------------------ files="*.[ch] s/*.h m/*.h config.h.in ../configure.in Makefile.in.in ../lib-src/*.[ch] ../lwlib/*.[ch]" gr Memory_Count Bytecount $files gr Lstream_Data_Count Bytecount $files gr Element_Count Elemcount $files gr Hash_Code Hashcode $files gr extcount bytecount $files gr bufpos charbpos $files gr bytind bytebpos $files gr memind membpos $files gr bufbyte intbyte $files gr Extcount Bytecount $files gr Bufpos Charbpos $files gr Bytind Bytebpos $files gr Memind Membpos $files gr Bufbyte Intbyte $files gr EXTCOUNT BYTECOUNT $files gr BUFPOS CHARBPOS $files gr BYTIND BYTEBPOS $files gr MEMIND MEMBPOS $files gr BUFBYTE INTBYTE $files gr MEMORY_COUNT BYTECOUNT $files gr LSTREAM_DATA_COUNT BYTECOUNT $files gr ELEMENT_COUNT ELEMCOUNT $files gr HASH_CODE HASHCODE $files ----------------------------------- cut ------------------------------------ `fixtypes.sh' is a Bourne-shell script; it uses 'gr': ----------------------------------- cut ------------------------------------ #!/bin/sh # Usage is like this: # gr FROM TO FILES ... # globally replace FROM with TO in FILES. FROM and TO are regular expressions. # backup files are stored in the `backup' directory. from="$1" to="$2" shift 2 echo ${1+"$@"} | xargs global-replace "s/$from/$to/g" ----------------------------------- cut ------------------------------------ `gr' in turn uses a Perl script to do its real work, `global-replace', which follows: ----------------------------------- cut ------------------------------------ : #-*- Perl -*- ### global-modify --- modify the contents of a file by a Perl expression ## Copyright (C) 1999 Martin Buchholz. ## Copyright (C) 2001 Ben Wing. ## Authors: Martin Buchholz <martin@xemacs.org>, Ben Wing <ben@xemacs.org> ## Maintainer: Ben Wing <ben@xemacs.org> ## Current Version: 1.0, May 5, 2001 # This program 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. # # This program 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. eval 'exec perl -w -S $0 ${1+"$@"}' if 0; use strict; use FileHandle; use Carp; use Getopt::Long; use File::Basename; (my $myName = $0) =~ s@.*/@@; my $usage=" Usage: $myName [--help] [--backup-dir=DIR] [--line-mode] [--hunk-mode] PERLEXPR FILE ... Globally modify a file, either line by line or in one big hunk. Typical usage is like this: [with GNU print, GNU xargs: guaranteed to handle spaces, quotes, etc. in file names] find . -name '*.[ch]' -print0 | xargs -0 $0 's/\bCONST\b/const/g'\n [with non-GNU print, xargs] find . -name '*.[ch]' -print | xargs $0 's/\bCONST\b/const/g'\n The file is read in, either line by line (with --line-mode specified) or in one big hunk (with --hunk-mode specified; it's the default), and the Perl expression is then evalled with \$_ set to the line or hunk of text, including the terminating newline if there is one. It should destructively modify the value there, storing the changed result in \$_. Files in which any modifications are made are backed up to the directory specified using --backup-dir, or to `backup' by default. To disable this, use --backup-dir= with no argument. Hunk mode is the default because it is MUCH MUCH faster than line-by-line. Use line-by-line only when it matters, e.g. you want to do a replacement only once per line (the default without the `g' argument). Conversely, when using hunk mode, *ALWAYS* use `g'; otherwise, you will only make one replacement in the entire file! "; my %options = (); $Getopt::Long::ignorecase = 0; &GetOptions ( \%options, 'help', 'backup-dir=s', 'line-mode', 'hunk-mode', ); die $usage if $options{"help"} or @ARGV <= 1; my $code = shift; die $usage if grep (-d || ! -w, @ARGV); sub SafeOpen { open ((my $fh = new FileHandle), $_[0]); confess "Can't open $_[0]: $!" if ! defined $fh; return $fh; } sub SafeClose { close $_[0] or confess "Can't close $_[0]: $!"; } sub FileContents { my $fh = SafeOpen ("< $_[0]"); my $olddollarslash = $/; local $/ = undef; my $contents = <$fh>; $/ = $olddollarslash; return $contents; } sub WriteStringToFile { my $fh = SafeOpen ("> $_[0]"); binmode $fh; print $fh $_[1] or confess "$_[0]: $!\n"; SafeClose $fh; } foreach my $file (@ARGV) { my $changed_p = 0; my $new_contents = ""; if ($options{"line-mode"}) { my $fh = SafeOpen $file; while (<$fh>) { my $save_line = $_; eval $code; $changed_p = 1 if $save_line ne $_; $new_contents .= $_; } } else { my $orig_contents = $_ = FileContents $file; eval $code; if ($_ ne $orig_contents) { $changed_p = 1; $new_contents = $_; } } if ($changed_p) { my $backdir = $options{"backup-dir"}; $backdir = "backup" if !defined ($backdir); if ($backdir) { my ($name, $path, $suffix) = fileparse ($file, ""); my $backfulldir = $path . $backdir; my $backfile = "$backfulldir/$name"; mkdir $backfulldir, 0755 unless -d $backfulldir; print "modifying $file (original saved in $backfile)\n"; rename $file, $backfile; } WriteStringToFile ($file, $new_contents); } } ----------------------------------- cut ------------------------------------ In addition to those programs, I needed to fix up a few other things, particularly relating to the duplicate definitions of types, now that some types merged with others. Specifically: 1. in lisp.h, removed duplicate declarations of Bytecount. The changed code should now look like this: (In each code snippet below, the first and last lines are the same as the original, as are all lines outside of those lines. That allows you to locate the section to be replaced, and replace the stuff in that section, verifying that there isn't anything new added that would need to be kept.) --------------------------------- snip ------------------------------------- /* Counts of bytes or chars */ typedef EMACS_INT Bytecount; typedef EMACS_INT Charcount; /* Counts of elements */ typedef EMACS_INT Elemcount; /* Hash codes */ typedef unsigned long Hashcode; /* ------------------------ dynamic arrays ------------------- */ --------------------------------- snip ------------------------------------- 2. in lstream.h, removed duplicate declaration of Bytecount. Rewrote the comment about this type. The changed code should now look like this: --------------------------------- snip ------------------------------------- #endif /* The have been some arguments over the what the type should be that specifies a count of bytes in a data block to be written out or read in, using Lstream_read(), Lstream_write(), and related functions. Originally it was long, which worked fine; Martin "corrected" these to size_t and ssize_t on the grounds that this is theoretically cleaner and is in keeping with the C standards. Unfortunately, this practice is horribly error-prone due to design flaws in the way that mixed signed/unsigned arithmetic happens. In fact, by doing this change, Martin introduced a subtle but fatal error that caused the operation of sending large mail messages to the SMTP server under Windows to fail. By putting all values back to be signed, avoiding any signed/unsigned mixing, the bug immediately went away. The type then in use was Lstream_Data_Count, so that it be reverted cleanly if a vote came to that. Now it is Bytecount. Some earlier comments about why the type must be signed: This MUST BE SIGNED, since it also is used in functions that return the number of bytes actually read to or written from in an operation, and these functions can return -1 to signal error. Note that the standard Unix read() and write() functions define the count going in as a size_t, which is UNSIGNED, and the count going out as an ssize_t, which is SIGNED. This is a horrible design flaw. Not only is it highly likely to lead to logic errors when a -1 gets interpreted as a large positive number, but operations are bound to fail in all sorts of horrible ways when a number in the upper-half of the size_t range is passed in -- this number is unrepresentable as an ssize_t, so code that checks to see how many bytes are actually written (which is mandatory if you are dealing with certain types of devices) will get completely screwed up. --ben */ typedef enum lstream_buffering --------------------------------- snip ------------------------------------- 3. in dumper.c, there are four places, all inside of switch() statements, where XD_BYTECOUNT appears twice as a case tag. In each case, the two case blocks contain identical code, and you should *REMOVE THE SECOND* and leave the first.
author ben
date Thu, 20 Sep 2001 06:31:11 +0000
parents 183866b06e0b
children 943eaba38521
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1 /* Primitives for word-abbrev mode.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
2 Copyright (C) 1985, 1986, 1992, 1993 Free Software Foundation, Inc.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
3
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
4 This file is part of XEmacs.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
5
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
6 XEmacs is free software; you can redistribute it and/or modify it
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
7 under the terms of the GNU General Public License as published by the
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
8 Free Software Foundation; either version 2, or (at your option) any
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
9 later version.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
10
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
11 XEmacs is distributed in the hope that it will be useful, but WITHOUT
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
14 for more details.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
15
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
16 You should have received a copy of the GNU General Public License
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
17 along with XEmacs; see the file COPYING. If not, write to
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
19 Boston, MA 02111-1307, USA. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
20
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
21 /* Synched up with: FSF 19.30. Note that there are many more functions in
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
22 FSF's abbrev.c. These have been moved into Lisp in XEmacs. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
23
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
24 /* Authorship:
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
25
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
26 FSF: Original version; a long time ago.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
27 JWZ or Mly: Mostly moved into Lisp; maybe 1992.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
28 Ben Wing: Some changes for Mule for 19.12.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
29 Hrvoje Niksic: Largely rewritten in June 1997.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
30 */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
31
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
32 /* This file has been Mule-ized. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
33
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
34 #include <config.h>
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
35 #include "lisp.h"
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
36
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
37 #include "buffer.h"
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
38 #include "commands.h"
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
39 #include "insdel.h"
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
40 #include "syntax.h"
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
41 #include "window.h"
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
42
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
43 /* An abbrev table is an obarray.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
44 Each defined abbrev is represented by a symbol in that obarray
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
45 whose print name is the abbreviation.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
46 The symbol's value is a string which is the expansion.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
47 If its function definition is non-nil, it is called
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
48 after the expansion is done.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
49 The plist slot of the abbrev symbol is its usage count. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
50
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
51 /* The table of global abbrevs. These are in effect
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
52 in any buffer in which abbrev mode is turned on. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
53 Lisp_Object Vglobal_abbrev_table;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
54
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
55 int abbrev_all_caps;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
56
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
57 /* Non-nil => use this location as the start of abbrev to expand
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
58 (rather than taking the word before point as the abbrev) */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
59 Lisp_Object Vabbrev_start_location;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
60
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
61 /* Buffer that Vabbrev_start_location applies to */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
62 Lisp_Object Vabbrev_start_location_buffer;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
63
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
64 /* The symbol representing the abbrev most recently expanded */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
65 Lisp_Object Vlast_abbrev;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
66
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
67 /* A string for the actual text of the abbrev most recently expanded.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
68 This has more info than Vlast_abbrev since case is significant. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
69 Lisp_Object Vlast_abbrev_text;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
70
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
71 /* Character address of start of last abbrev expanded */
458
c33ae14dd6d0 Import from CVS: tag r21-2-44
cvs
parents: 440
diff changeset
72 Fixnum last_abbrev_location;
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
73
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
74 /* Hook to run before expanding any abbrev. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
75 Lisp_Object Vpre_abbrev_expand_hook, Qpre_abbrev_expand_hook;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
76
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
77
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
78 struct abbrev_match_mapper_closure {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
79 struct buffer *buf;
440
8de8e3f6228a Import from CVS: tag r21-2-28
cvs
parents: 428
diff changeset
80 Lisp_Char_Table *chartab;
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
81 Charcount point, maxlen;
440
8de8e3f6228a Import from CVS: tag r21-2-28
cvs
parents: 428
diff changeset
82 Lisp_Symbol *found;
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
83 };
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
84
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
85 /* For use by abbrev_match(): Match SYMBOL's name against buffer text
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
86 before point, case-insensitively. When found, return non-zero, so
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
87 that map_obarray terminates mapping. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
88 static int
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
89 abbrev_match_mapper (Lisp_Object symbol, void *arg)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
90 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
91 struct abbrev_match_mapper_closure *closure =
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
92 (struct abbrev_match_mapper_closure *)arg;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
93 Charcount abbrev_length;
440
8de8e3f6228a Import from CVS: tag r21-2-28
cvs
parents: 428
diff changeset
94 Lisp_Symbol *sym = XSYMBOL (symbol);
8de8e3f6228a Import from CVS: tag r21-2-28
cvs
parents: 428
diff changeset
95 Lisp_String *abbrev;
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
96
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
97 /* symbol_value should be OK here, because abbrevs are not expected
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
98 to contain any SYMBOL_MAGIC stuff. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
99 if (UNBOUNDP (symbol_value (sym)) || NILP (symbol_value (sym)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
100 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
101 /* The symbol value of nil means that abbrev got undefined. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
102 return 0;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
103 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
104 abbrev = symbol_name (sym);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
105 abbrev_length = string_char_length (abbrev);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
106 if (abbrev_length > closure->maxlen)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
107 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
108 /* This abbrev is too large -- it wouldn't fit. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
109 return 0;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
110 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
111 /* If `bar' is an abbrev, and a user presses `fubar<SPC>', we don't
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
112 normally want to expand it. OTOH, if the abbrev begins with
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
113 non-word syntax (e.g. `#if'), it is OK to abbreviate it anywhere. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
114 if (abbrev_length < closure->maxlen && abbrev_length > 0
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
115 && (WORD_SYNTAX_P (closure->chartab, string_char (abbrev, 0)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
116 && (WORD_SYNTAX_P (closure->chartab,
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
117 BUF_FETCH_CHAR (closure->buf,
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
118 closure->point - (abbrev_length + 1)))))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
119 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
120 return 0;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
121 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
122 /* Match abbreviation string against buffer text. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
123 {
665
fdefd0186b75 [xemacs-hg @ 2001-09-20 06:28:42 by ben]
ben
parents: 563
diff changeset
124 Intbyte *ptr = string_data (abbrev);
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
125 Charcount idx;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
126
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
127 for (idx = 0; idx < abbrev_length; idx++)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
128 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
129 if (DOWNCASE (closure->buf,
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
130 BUF_FETCH_CHAR (closure->buf,
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
131 closure->point - abbrev_length + idx))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
132 != DOWNCASE (closure->buf, charptr_emchar (ptr)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
133 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
134 break;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
135 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
136 INC_CHARPTR (ptr);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
137 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
138 if (idx == abbrev_length)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
139 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
140 /* This is the one. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
141 closure->found = sym;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
142 return 1;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
143 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
144 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
145 return 0;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
146 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
147
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
148 /* Match the buffer text against names of symbols in obarray. Returns
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
149 the matching symbol, or 0 if not found. */
440
8de8e3f6228a Import from CVS: tag r21-2-28
cvs
parents: 428
diff changeset
150 static Lisp_Symbol *
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
151 abbrev_match (struct buffer *buf, Lisp_Object obarray)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
152 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
153 struct abbrev_match_mapper_closure closure;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
154
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
155 /* Precalculate some stuff, so mapper function needn't to it in each
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
156 iteration. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
157 closure.buf = buf;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
158 closure.point = BUF_PT (buf);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
159 closure.maxlen = closure.point - BUF_BEGV (buf);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
160 closure.chartab = XCHAR_TABLE (buf->mirror_syntax_table);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
161 closure.found = 0;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
162
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
163 map_obarray (obarray, abbrev_match_mapper, &closure);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
164
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
165 return closure.found;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
166 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
167
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
168 /* Take the word before point (or Vabbrev_start_location, if non-nil),
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
169 and look it up in OBARRAY, and return the symbol (or zero). This
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
170 used to be the default method of searching, with the obvious
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
171 limitation that the abbrevs may consist only of word characters.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
172 It is an order of magnitude faster than the proper abbrev_match(),
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
173 but then again, vi is an order of magnitude faster than Emacs.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
174
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
175 This speed difference should be unnoticeable, though. I have tested
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
176 the degenerated cases of thousands of abbrevs being defined, and
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
177 abbrev_match() was still fast enough for normal operation. */
440
8de8e3f6228a Import from CVS: tag r21-2-28
cvs
parents: 428
diff changeset
178 static Lisp_Symbol *
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
179 abbrev_oblookup (struct buffer *buf, Lisp_Object obarray)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
180 {
665
fdefd0186b75 [xemacs-hg @ 2001-09-20 06:28:42 by ben]
ben
parents: 563
diff changeset
181 Charbpos wordstart, wordend;
fdefd0186b75 [xemacs-hg @ 2001-09-20 06:28:42 by ben]
ben
parents: 563
diff changeset
182 Intbyte *word, *p;
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
183 Bytecount idx;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
184 Lisp_Object lookup;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
185
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
186 CHECK_VECTOR (obarray);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
187
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
188 if (!NILP (Vabbrev_start_location))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
189 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
190 wordstart = get_buffer_pos_char (buf, Vabbrev_start_location,
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
191 GB_COERCE_RANGE);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
192 Vabbrev_start_location = Qnil;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
193 #if 0
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
194 /* Previously, abbrev-prefix-mark crockishly inserted a dash to
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
195 indicate the abbrev start point. It now uses an extent with
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
196 a begin glyph so there's no dash to remove. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
197 if (wordstart != BUF_ZV (buf)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
198 && BUF_FETCH_CHAR (buf, wordstart) == '-')
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
199 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
200 buffer_delete_range (buf, wordstart, wordstart + 1, 0);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
201 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
202 #endif
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
203 wordend = BUF_PT (buf);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
204 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
205 else
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
206 {
665
fdefd0186b75 [xemacs-hg @ 2001-09-20 06:28:42 by ben]
ben
parents: 563
diff changeset
207 Charbpos point = BUF_PT (buf);
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
208
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
209 wordstart = scan_words (buf, point, -1);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
210 if (!wordstart)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
211 return 0;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
212
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
213 wordend = scan_words (buf, wordstart, 1);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
214 if (!wordend)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
215 return 0;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
216 if (wordend > BUF_ZV (buf))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
217 wordend = BUF_ZV (buf);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
218 if (wordend > point)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
219 wordend = point;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
220 /* Unlike the original function, we allow expansion only after
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
221 the abbrev, not preceded by a number of spaces. This is
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
222 because of consistency with abbrev_match. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
223 if (wordend < point)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
224 return 0;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
225 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
226
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
227 if (wordend <= wordstart)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
228 return 0;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
229
665
fdefd0186b75 [xemacs-hg @ 2001-09-20 06:28:42 by ben]
ben
parents: 563
diff changeset
230 p = word = (Intbyte *) alloca (MAX_EMCHAR_LEN * (wordend - wordstart));
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
231 for (idx = wordstart; idx < wordend; idx++)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
232 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
233 Emchar c = BUF_FETCH_CHAR (buf, idx);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
234 if (UPPERCASEP (buf, c))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
235 c = DOWNCASE (buf, c);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
236 p += set_charptr_emchar (p, c);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
237 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
238 lookup = oblookup (obarray, word, p - word);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
239 if (SYMBOLP (lookup) && !NILP (symbol_value (XSYMBOL (lookup))))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
240 return XSYMBOL (lookup);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
241 else
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
242 return NULL;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
243 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
244
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
245 /* Return non-zero if OBARRAY contains an interned symbol ` '. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
246 static int
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
247 obarray_has_blank_p (Lisp_Object obarray)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
248 {
665
fdefd0186b75 [xemacs-hg @ 2001-09-20 06:28:42 by ben]
ben
parents: 563
diff changeset
249 return !ZEROP (oblookup (obarray, (Intbyte *)" ", 1));
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
250 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
251
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
252 /* Analyze case in the buffer substring, and report it. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
253 static void
665
fdefd0186b75 [xemacs-hg @ 2001-09-20 06:28:42 by ben]
ben
parents: 563
diff changeset
254 abbrev_count_case (struct buffer *buf, Charbpos pos, Charcount length,
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
255 int *lccount, int *uccount)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
256 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
257 *lccount = *uccount = 0;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
258 while (length--)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
259 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
260 Emchar c = BUF_FETCH_CHAR (buf, pos);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
261 if (UPPERCASEP (buf, c))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
262 ++*uccount;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
263 else if (LOWERCASEP (buf, c))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
264 ++*lccount;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
265 ++pos;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
266 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
267 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
268
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
269 DEFUN ("expand-abbrev", Fexpand_abbrev, 0, 0, "", /*
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
270 Expand the abbrev before point, if any.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
271 Effective when explicitly called even when `abbrev-mode' is nil.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
272 Returns the abbrev symbol, if expansion took place.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
273 If no abbrev matched, but `pre-abbrev-expand-hook' changed the buffer,
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
274 returns t.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
275 */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
276 ())
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
277 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
278 /* This function can GC */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
279 struct buffer *buf = current_buffer;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
280 int oldmodiff = BUF_MODIFF (buf);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
281 Lisp_Object pre_modiff_p;
665
fdefd0186b75 [xemacs-hg @ 2001-09-20 06:28:42 by ben]
ben
parents: 563
diff changeset
282 Charbpos point; /* position of point */
fdefd0186b75 [xemacs-hg @ 2001-09-20 06:28:42 by ben]
ben
parents: 563
diff changeset
283 Charbpos abbrev_start; /* position of abbreviation beginning */
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
284
440
8de8e3f6228a Import from CVS: tag r21-2-28
cvs
parents: 428
diff changeset
285 Lisp_Symbol *(*fun) (struct buffer *, Lisp_Object);
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
286
440
8de8e3f6228a Import from CVS: tag r21-2-28
cvs
parents: 428
diff changeset
287 Lisp_Symbol *abbrev_symbol;
8de8e3f6228a Import from CVS: tag r21-2-28
cvs
parents: 428
diff changeset
288 Lisp_String *abbrev_string;
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
289 Lisp_Object expansion, count, hook;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
290 Charcount abbrev_length;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
291 int lccount, uccount;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
292
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
293 run_hook (Qpre_abbrev_expand_hook);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
294 /* If the hook changes the buffer, treat that as having "done an
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
295 expansion". */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
296 pre_modiff_p = (BUF_MODIFF (buf) != oldmodiff ? Qt : Qnil);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
297
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
298 abbrev_symbol = NULL;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
299 if (!BUFFERP (Vabbrev_start_location_buffer) ||
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
300 XBUFFER (Vabbrev_start_location_buffer) != buf)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
301 Vabbrev_start_location = Qnil;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
302 /* We use the more general abbrev_match() if the obarray blank flag
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
303 is not set, and Vabbrev_start_location is nil. Otherwise, use
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
304 abbrev_oblookup(). */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
305 #define MATCHFUN(tbl) ((obarray_has_blank_p (tbl) \
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
306 && NILP (Vabbrev_start_location)) \
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
307 ? abbrev_match : abbrev_oblookup)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
308 if (!NILP (buf->abbrev_table))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
309 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
310 fun = MATCHFUN (buf->abbrev_table);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
311 abbrev_symbol = fun (buf, buf->abbrev_table);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
312 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
313 if (!abbrev_symbol && !NILP (Vglobal_abbrev_table))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
314 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
315 fun = MATCHFUN (Vglobal_abbrev_table);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
316 abbrev_symbol = fun (buf, Vglobal_abbrev_table);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
317 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
318 if (!abbrev_symbol)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
319 return pre_modiff_p;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
320
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
321 /* NOTE: we hope that `pre-abbrev-expand-hook' didn't do something
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
322 nasty, such as changed the buffer. Here we protect against the
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
323 buffer getting killed. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
324 if (! BUFFER_LIVE_P (buf))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
325 return Qnil;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
326 point = BUF_PT (buf);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
327
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
328 /* OK, we're out of the must-be-fast part. An abbreviation matched.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
329 Now find the parameters, insert the expansion, and make it all
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
330 look pretty. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
331 abbrev_string = symbol_name (abbrev_symbol);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
332 abbrev_length = string_char_length (abbrev_string);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
333 abbrev_start = point - abbrev_length;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
334
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
335 expansion = symbol_value (abbrev_symbol);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
336 CHECK_STRING (expansion);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
337
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
338 count = symbol_plist (abbrev_symbol); /* Gag */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
339 if (NILP (count))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
340 count = Qzero;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
341 else
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
342 CHECK_NATNUM (count);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
343 symbol_plist (abbrev_symbol) = make_int (1 + XINT (count));
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
344
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
345 /* Count the case in the original text. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
346 abbrev_count_case (buf, abbrev_start, abbrev_length, &lccount, &uccount);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
347
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
348 /* Remember the last abbrev text, location, etc. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
349 XSETSYMBOL (Vlast_abbrev, abbrev_symbol);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
350 Vlast_abbrev_text =
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
351 make_string_from_buffer (buf, abbrev_start, abbrev_length);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
352 last_abbrev_location = abbrev_start;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
353
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
354 /* Add an undo boundary, in case we are doing this for a
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
355 self-inserting command which has avoided making one so far. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
356 if (INTERACTIVE)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
357 Fundo_boundary ();
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
358
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
359 /* Remove the abbrev */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
360 buffer_delete_range (buf, abbrev_start, point, 0);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
361 /* And insert the expansion. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
362 buffer_insert_lisp_string (buf, expansion);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
363 point = BUF_PT (buf);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
364
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
365 /* Now fiddle with the case. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
366 if (uccount && !lccount)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
367 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
368 /* Abbrev was all caps */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
369 if (!abbrev_all_caps
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
370 && scan_words (buf, point, -1) > scan_words (buf, abbrev_start, 1))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
371 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
372 Fupcase_initials_region (make_int (abbrev_start), make_int (point),
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
373 make_buffer (buf));
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
374 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
375 else
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
376 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
377 /* If expansion is one word, or if user says so, upcase it all. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
378 Fupcase_region (make_int (abbrev_start), make_int (point),
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
379 make_buffer (buf));
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
380 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
381 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
382 else if (uccount)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
383 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
384 /* Abbrev included some caps. Cap first initial of expansion */
665
fdefd0186b75 [xemacs-hg @ 2001-09-20 06:28:42 by ben]
ben
parents: 563
diff changeset
385 Charbpos pos = abbrev_start;
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
386 /* Find the initial. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
387 while (pos < point
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
388 && !WORD_SYNTAX_P (XCHAR_TABLE (buf->mirror_syntax_table),
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
389 BUF_FETCH_CHAR (buf, pos)))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
390 pos++;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
391 /* Change just that. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
392 Fupcase_initials_region (make_int (pos), make_int (pos + 1),
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
393 make_buffer (buf));
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
394 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
395
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
396 hook = symbol_function (abbrev_symbol);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
397 if (!NILP (hook) && !UNBOUNDP (hook))
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
398 call0 (hook);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
399
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
400 return Vlast_abbrev;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
401 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
402
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
403
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
404 void
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
405 syms_of_abbrev (void)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
406 {
563
183866b06e0b [xemacs-hg @ 2001-05-24 07:50:48 by ben]
ben
parents: 458
diff changeset
407 DEFSYMBOL (Qpre_abbrev_expand_hook);
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
408 DEFSUBR (Fexpand_abbrev);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
409 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
410
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
411 void
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
412 vars_of_abbrev (void)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
413 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
414 DEFVAR_LISP ("global-abbrev-table", &Vglobal_abbrev_table /*
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
415 The abbrev table whose abbrevs affect all buffers.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
416 Each buffer may also have a local abbrev table.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
417 If it does, the local table overrides the global one
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
418 for any particular abbrev defined in both.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
419 */ );
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
420 Vglobal_abbrev_table = Qnil; /* setup by Lisp code */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
421
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
422 DEFVAR_LISP ("last-abbrev", &Vlast_abbrev /*
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
423 The abbrev-symbol of the last abbrev expanded.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
424 See the function `abbrev-symbol'.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
425 */ );
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
426
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
427 DEFVAR_LISP ("last-abbrev-text", &Vlast_abbrev_text /*
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
428 The exact text of the last abbrev expanded.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
429 nil if the abbrev has already been unexpanded.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
430 */ );
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
431
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
432 DEFVAR_INT ("last-abbrev-location", &last_abbrev_location /*
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
433 The location of the start of the last abbrev expanded.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
434 */ );
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
435
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
436 Vlast_abbrev = Qnil;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
437 Vlast_abbrev_text = Qnil;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
438 last_abbrev_location = 0;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
439
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
440 DEFVAR_LISP ("abbrev-start-location", &Vabbrev_start_location /*
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
441 Buffer position for `expand-abbrev' to use as the start of the abbrev.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
442 nil means use the word before point as the abbrev.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
443 Calling `expand-abbrev' sets this to nil.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
444 */ );
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
445 Vabbrev_start_location = Qnil;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
446
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
447 DEFVAR_LISP ("abbrev-start-location-buffer", &Vabbrev_start_location_buffer /*
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
448 Buffer that `abbrev-start-location' has been set for.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
449 Trying to expand an abbrev in any other buffer clears `abbrev-start-location'.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
450 */ );
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
451 Vabbrev_start_location_buffer = Qnil;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
452
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
453 DEFVAR_BOOL ("abbrev-all-caps", &abbrev_all_caps /*
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
454 *Non-nil means expand multi-word abbrevs all caps if abbrev was so.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
455 */ );
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
456 abbrev_all_caps = 0;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
457
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
458 DEFVAR_LISP ("pre-abbrev-expand-hook", &Vpre_abbrev_expand_hook /*
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
459 Function or functions to be called before abbrev expansion is done.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
460 This is the first thing that `expand-abbrev' does, and so this may change
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
461 the current abbrev table before abbrev lookup happens.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
462 */ );
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
463 Vpre_abbrev_expand_hook = Qnil;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
464 }