(M-40132'): Unify GT-53970.
[chise/xemacs-chise.git-] / src / cmds.c
1 /* Simple built-in editing commands.
2    Copyright (C) 1985, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
3    Copyright (C) 2001 MORIOKA Tomohiko
4
5 This file is part of XEmacs.
6
7 XEmacs is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 2, or (at your option) any
10 later version.
11
12 XEmacs is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with XEmacs; see the file COPYING.  If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA.  */
21
22 /* Synched up with: Mule 2.0, FSF 19.30. */
23
24 #include <config.h>
25 #include "lisp.h"
26 #include "commands.h"
27 #include "buffer.h"
28 #include "syntax.h"
29 #include "insdel.h"
30
31 Lisp_Object Qkill_forward_chars;
32 Lisp_Object Qself_insert_command;
33 Lisp_Object Qno_self_insert;
34
35 Lisp_Object Vblink_paren_function;
36
37 /* A possible value for a buffer's overwrite-mode variable.  */
38 Lisp_Object Qoverwrite_mode_binary;
39
40 /* Non-nil means put this face on the next self-inserting character.  */
41 Lisp_Object Vself_insert_face;
42
43 /* This is the command that set up Vself_insert_face.  */
44 Lisp_Object Vself_insert_face_command;
45
46 /* A char-table for characters which may invoke auto-filling.  */
47 Lisp_Object Vauto_fill_chars;
48 \f
49 DEFUN ("forward-char", Fforward_char, 0, 2, "_p", /*
50 Move point right COUNT characters (left if COUNT is negative).
51 On attempt to pass end of buffer, stop and signal `end-of-buffer'.
52 On attempt to pass beginning of buffer, stop and signal `beginning-of-buffer'.
53 On reaching end of buffer, stop and signal error.
54 */
55        (count, buffer))
56 {
57   struct buffer *buf = decode_buffer (buffer, 1);
58   EMACS_INT n;
59
60   if (NILP (count))
61     n = 1;
62   else
63     {
64       CHECK_INT (count);
65       n = XINT (count);
66     }
67
68   /* This used to just set point to point + XINT (count), and then check
69      to see if it was within boundaries.  But now that SET_PT can
70      potentially do a lot of stuff (calling entering and exiting
71      hooks, etcetera), that's not a good approach.  So we validate the
72      proposed position, then set point.  */
73   {
74     Bufpos new_point = BUF_PT (buf) + n;
75
76     if (new_point < BUF_BEGV (buf))
77       {
78         BUF_SET_PT (buf, BUF_BEGV (buf));
79         Fsignal (Qbeginning_of_buffer, Qnil);
80         return Qnil;
81       }
82     if (new_point > BUF_ZV (buf))
83       {
84         BUF_SET_PT (buf, BUF_ZV (buf));
85         Fsignal (Qend_of_buffer, Qnil);
86         return Qnil;
87       }
88
89     BUF_SET_PT (buf, new_point);
90   }
91
92   return Qnil;
93 }
94
95 DEFUN ("backward-char", Fbackward_char, 0, 2, "_p", /*
96 Move point left COUNT characters (right if COUNT is negative).
97 On attempt to pass end of buffer, stop and signal `end-of-buffer'.
98 On attempt to pass beginning of buffer, stop and signal `beginning-of-buffer'.
99 */
100        (count, buffer))
101 {
102   if (NILP (count))
103     count = make_int (-1);
104   else
105     {
106       CHECK_INT (count);
107       count = make_int (- XINT (count));
108     }
109   return Fforward_char (count, buffer);
110 }
111
112 DEFUN ("forward-line", Fforward_line, 0, 2, "_p", /*
113 Move COUNT lines forward (backward if COUNT is negative).
114 Precisely, if point is on line I, move to the start of line I + COUNT.
115 If there isn't room, go as far as possible (no error).
116 Returns the count of lines left to move.  If moving forward,
117 that is COUNT - number of lines moved; if backward, COUNT + number moved.
118 With positive COUNT, a non-empty line at the end counts as one line
119   successfully moved (for the return value).
120 If BUFFER is nil, the current buffer is assumed.
121 */
122        (count, buffer))
123 {
124   struct buffer *buf = decode_buffer (buffer, 1);
125   Bufpos pos2 = BUF_PT (buf);
126   Bufpos pos;
127   EMACS_INT n, shortage, negp;
128
129   if (NILP (count))
130     n = 1;
131   else
132     {
133       CHECK_INT (count);
134       n = XINT (count);
135     }
136
137   negp = n <= 0;
138   pos = scan_buffer (buf, '\n', pos2, 0, n - negp, &shortage, 1);
139   if (shortage > 0
140       && (negp
141           || (BUF_ZV (buf) > BUF_BEGV (buf)
142               && pos != pos2
143               && BUF_FETCH_CHAR (buf, pos - 1) != '\n')))
144     shortage--;
145   BUF_SET_PT (buf, pos);
146   return make_int (negp ? - shortage : shortage);
147 }
148
149 DEFUN ("point-at-bol", Fpoint_at_bol, 0, 2, 0, /*
150 Return the character position of the first character on the current line.
151 With argument COUNT not nil or 1, move forward COUNT - 1 lines first.
152 If scan reaches end of buffer, return that position.
153 This function does not move point.
154 */
155        (count, buffer))
156 {
157   struct buffer *b = decode_buffer (buffer, 1);
158   REGISTER int orig, end;
159
160   XSETBUFFER (buffer, b);
161   if (NILP (count))
162     count = make_int (0);
163   else
164     {
165       CHECK_INT (count);
166       count = make_int (XINT (count) - 1);
167     }
168
169   orig = BUF_PT (b);
170   Fforward_line (count, buffer);
171   end = BUF_PT (b);
172   BUF_SET_PT (b, orig);
173
174   return make_int (end);
175 }
176
177 DEFUN ("beginning-of-line", Fbeginning_of_line, 0, 2, "_p", /*
178 Move point to beginning of current line.
179 With argument COUNT not nil or 1, move forward COUNT - 1 lines first.
180 If scan reaches end of buffer, stop there without error.
181 If BUFFER is nil, the current buffer is assumed.
182 */
183        (count, buffer))
184 {
185   struct buffer *b = decode_buffer (buffer, 1);
186
187   BUF_SET_PT (b, XINT (Fpoint_at_bol (count, buffer)));
188   return Qnil;
189 }
190
191 DEFUN ("point-at-eol", Fpoint_at_eol, 0, 2, 0, /*
192 Return the character position of the last character on the current line.
193 With argument COUNT not nil or 1, move forward COUNT - 1 lines first.
194 If scan reaches end of buffer, return that position.
195 This function does not move point.
196 */
197        (count, buffer))
198 {
199   struct buffer *buf = decode_buffer (buffer, 1);
200   EMACS_INT n;
201
202   if (NILP (count))
203     n = 1;
204   else
205     {
206       CHECK_INT (count);
207       n = XINT (count);
208     }
209
210   return make_int (find_before_next_newline (buf, BUF_PT (buf), 0,
211                                              n - (n <= 0)));
212 }
213
214 DEFUN ("end-of-line", Fend_of_line, 0, 2, "_p", /*
215 Move point to end of current line.
216 With argument COUNT not nil or 1, move forward COUNT - 1 lines first.
217 If scan reaches end of buffer, stop there without error.
218 If BUFFER is nil, the current buffer is assumed.
219 */
220        (count, buffer))
221 {
222   struct buffer *b = decode_buffer (buffer, 1);
223
224   BUF_SET_PT (b, XINT (Fpoint_at_eol (count, buffer)));
225   return Qnil;
226 }
227
228 DEFUN ("delete-char", Fdelete_char, 0, 2, "*p\nP", /*
229 Delete the following COUNT characters (previous, with negative COUNT).
230 Optional second arg KILLP non-nil means kill instead (save in kill ring).
231 Interactively, COUNT is the prefix arg, and KILLP is set if
232 COUNT was explicitly specified.
233 */
234        (count, killp))
235 {
236   /* This function can GC */
237   Bufpos pos;
238   struct buffer *buf = current_buffer;
239   EMACS_INT n;
240
241   if (NILP (count))
242     n = 1;
243   else
244     {
245       CHECK_INT (count);
246       n = XINT (count);
247     }
248
249   pos = BUF_PT (buf) + n;
250   if (NILP (killp))
251     {
252       if (n < 0)
253         {
254           if (pos < BUF_BEGV (buf))
255             signal_error (Qbeginning_of_buffer, Qnil);
256           else
257             buffer_delete_range (buf, pos, BUF_PT (buf), 0);
258         }
259       else
260         {
261           if (pos > BUF_ZV (buf))
262             signal_error (Qend_of_buffer, Qnil);
263           else
264             buffer_delete_range (buf, BUF_PT (buf), pos, 0);
265         }
266     }
267   else
268     {
269       call1 (Qkill_forward_chars, count);
270     }
271   return Qnil;
272 }
273
274 DEFUN ("delete-backward-char", Fdelete_backward_char, 0, 2, "*p\nP", /*
275 Delete the previous COUNT characters (following, with negative COUNT).
276 Optional second arg KILLP non-nil means kill instead (save in kill ring).
277 Interactively, COUNT is the prefix arg, and KILLP is set if
278 COUNT was explicitly specified.
279 */
280        (count, killp))
281 {
282   /* This function can GC */
283   EMACS_INT n;
284
285   if (NILP (count))
286     n = 1;
287   else
288     {
289       CHECK_INT (count);
290       n = XINT (count);
291     }
292
293   return Fdelete_char (make_int (- n), killp);
294 }
295
296 static void internal_self_insert (Emchar ch, int noautofill);
297
298 DEFUN ("self-insert-command", Fself_insert_command, 1, 1, "*p", /*
299 Insert the character you type.
300 Whichever character you type to run this command is inserted.
301 If a prefix arg COUNT is specified, the character is inserted COUNT times.
302 */
303        (count))
304 {
305   /* This function can GC */
306   Emchar ch;
307   Lisp_Object c;
308   EMACS_INT n;
309
310   CHECK_NATNUM (count);
311   n = XINT (count);
312
313   if (CHAR_OR_CHAR_INTP (Vlast_command_char))
314     c = Vlast_command_char;
315   else
316     c = Fevent_to_character (Vlast_command_event, Qnil, Qnil, Qt);
317
318   if (NILP (c))
319     signal_simple_error ("Last typed character has no ASCII equivalent",
320                          Fcopy_event (Vlast_command_event, Qnil));
321
322   CHECK_CHAR_COERCE_INT (c);
323
324   ch = XCHAR (c);
325
326   while (n--)
327     internal_self_insert (ch, (n != 0));
328
329   return Qnil;
330 }
331
332 /* Insert character C1.  If NOAUTOFILL is nonzero, don't do autofill
333    even if it is enabled.
334
335    FSF:
336
337    If this insertion is suitable for direct output (completely simple),
338    return 0.  A value of 1 indicates this *might* not have been simple.
339    A value of 2 means this did things that call for an undo boundary.  */
340
341 static void
342 internal_self_insert (Emchar c1, int noautofill)
343 {
344   /* This function can GC */
345   /* int hairy = 0; -- unused */
346   REGISTER enum syntaxcode synt;
347   REGISTER Emchar c2;
348   Lisp_Object overwrite;
349   Lisp_Char_Table *syntax_table;
350   struct buffer *buf = current_buffer;
351   int tab_width;
352
353   overwrite = buf->overwrite_mode;
354 #ifdef UTF2000
355   syntax_table = XCHAR_TABLE (buf->syntax_table);
356 #else
357   syntax_table = XCHAR_TABLE (buf->mirror_syntax_table);
358 #endif
359
360 #if 0
361   /* No, this is very bad, it makes undo *always* undo a character at a time
362      instead of grouping consecutive self-inserts together.  Nasty nasty.
363    */
364   if (!NILP (Vbefore_change_functions) || !NILP (Vafter_change_functions)
365       || !NILP (Vbefore_change_function) || !NILP (Vafter_change_function))
366     hairy = 1;
367 #endif
368
369   if (!NILP (overwrite)
370       && BUF_PT (buf) < BUF_ZV (buf)
371       && (EQ (overwrite, Qoverwrite_mode_binary)
372           || (c1 != '\n' && BUF_FETCH_CHAR (buf, BUF_PT (buf)) != '\n'))
373       && (EQ (overwrite, Qoverwrite_mode_binary)
374           || BUF_FETCH_CHAR (buf, BUF_PT (buf)) != '\t'
375           || ((tab_width = XINT (buf->tab_width), tab_width <= 0)
376           || tab_width > 20
377           || !((current_column (buf) + 1) % tab_width))))
378     {
379       buffer_delete_range (buf, BUF_PT (buf), BUF_PT (buf) + 1, 0);
380       /* hairy = 2; */
381     }
382
383   if (!NILP (buf->abbrev_mode)
384       && !WORD_SYNTAX_P (syntax_table, c1)
385       && NILP (buf->read_only)
386       && BUF_PT (buf) > BUF_BEGV (buf))
387     {
388       c2 = BUF_FETCH_CHAR (buf, BUF_PT (buf) - 1);
389
390       if (WORD_SYNTAX_P (syntax_table, c2))
391         {
392 #if 1
393           Fexpand_abbrev ();
394 #else  /* FSFmacs */
395           Lisp_Object sym = Fexpand_abbrev ();
396
397           /* I think this is too bogus to add.  The function should
398              have a way of examining the character to be inserted, so
399              it can decide whether to insert it or not.  We should
400              design it better than that.  */
401
402           /* Here FSFmacs remembers MODIFF, compares it after
403              Fexpand_abbrev() finishes, and updates HAIRY.  */
404
405           /* NOTE: we cannot simply check for Vlast_abbrev, because
406              Fexpand_abbrev() can bail out before setting it to
407              anything meaningful, leaving us stuck with an old value.
408              Thus Fexpand_abbrev() was extended to return the actual
409              abbrev symbol.  */
410           if (!NILP (sym)
411               && !NILP (symbol_function (XSYMBOL (sym)))
412               && SYMBOLP (symbol_function (XSYMBOL (sym))))
413             {
414               Lisp_Object prop = Fget (symbol_function (XSYMBOL (sym)),
415                                        Qno_self_insert, Qnil);
416               if (!NILP (prop))
417                 return;
418             }
419 #endif /* FSFmacs */
420         }
421     }
422   if ((CHAR_TABLEP (Vauto_fill_chars)
423        ? !NILP (XCHAR_TABLE_VALUE_UNSAFE (Vauto_fill_chars, c1))
424        : (c1 == ' ' || c1 == '\n'))
425       && !noautofill
426       && !NILP (buf->auto_fill_function))
427     {
428       buffer_insert_emacs_char (buf, c1);
429       if (c1 == '\n')
430         /* After inserting a newline, move to previous line and fill */
431         /* that.  Must have the newline in place already so filling and */
432         /* justification, if any, know where the end is going to be. */
433         BUF_SET_PT (buf, BUF_PT (buf) - 1);
434       call0 (buf->auto_fill_function);
435       if (c1 == '\n')
436         BUF_SET_PT (buf, BUF_PT (buf) + 1);
437       /* hairy = 2; */
438     }
439   else
440     buffer_insert_emacs_char (buf, c1);
441
442   /* If previous command specified a face to use, use it.  */
443   if (!NILP (Vself_insert_face)
444       && EQ (Vlast_command, Vself_insert_face_command))
445     {
446       Lisp_Object before = make_int (BUF_PT (buf) - 1);
447       Lisp_Object after  = make_int (BUF_PT (buf));
448       Fput_text_property (before, after, Qface, Vself_insert_face, Qnil);
449       Fput_text_property (before, after, Qstart_open, Qt, Qnil);
450       Fput_text_property (before, after, Qend_open, Qnil, Qnil);
451       /* #### FSFmacs properties are normally closed ("sticky") on the
452          end but not the beginning.  It's the opposite for us. */
453       Vself_insert_face = Qnil;
454     }
455   synt = SYNTAX (syntax_table, c1);
456   if ((synt == Sclose || synt == Smath)
457       && !NILP (Vblink_paren_function) && INTERACTIVE
458       && !noautofill)
459     {
460       call0 (Vblink_paren_function);
461       /* hairy = 2; */
462     }
463
464   /* return hairy; */
465 }
466
467 /* (this comes from Mule but is a generally good idea) */
468
469 DEFUN ("self-insert-internal", Fself_insert_internal, 1, 1, 0, /*
470 Invoke `self-insert-command' as if CHARACTER is entered from keyboard.
471 */
472        (character))
473 {
474   /* This function can GC */
475   CHECK_CHAR_COERCE_INT (character);
476   internal_self_insert (XCHAR (character), 0);
477   return Qnil;
478 }
479 \f
480 /* module initialization */
481
482 void
483 syms_of_cmds (void)
484 {
485   defsymbol (&Qkill_forward_chars, "kill-forward-chars");
486   defsymbol (&Qself_insert_command, "self-insert-command");
487   defsymbol (&Qoverwrite_mode_binary, "overwrite-mode-binary");
488   defsymbol (&Qno_self_insert, "no-self-insert");
489
490   DEFSUBR (Fforward_char);
491   DEFSUBR (Fbackward_char);
492   DEFSUBR (Fforward_line);
493   DEFSUBR (Fbeginning_of_line);
494   DEFSUBR (Fend_of_line);
495
496   DEFSUBR (Fpoint_at_bol);
497   DEFSUBR (Fpoint_at_eol);
498
499   DEFSUBR (Fdelete_char);
500   DEFSUBR (Fdelete_backward_char);
501
502   DEFSUBR (Fself_insert_command);
503   DEFSUBR (Fself_insert_internal);
504 }
505
506 void
507 vars_of_cmds (void)
508 {
509   DEFVAR_LISP ("self-insert-face", &Vself_insert_face /*
510 If non-nil, set the face of the next self-inserting character to this.
511 See also `self-insert-face-command'.
512 */ );
513   Vself_insert_face = Qnil;
514
515   DEFVAR_LISP ("self-insert-face-command", &Vself_insert_face_command /*
516 This is the command that set up `self-insert-face'.
517 If `last-command' does not equal this value, we ignore `self-insert-face'.
518 */ );
519   Vself_insert_face_command = Qnil;
520
521   DEFVAR_LISP ("blink-paren-function", &Vblink_paren_function /*
522 Function called, if non-nil, whenever a close parenthesis is inserted.
523 More precisely, a char with closeparen syntax is self-inserted.
524 */ );
525   Vblink_paren_function = Qnil;
526
527   DEFVAR_LISP ("auto-fill-chars", &Vauto_fill_chars /*
528 A char-table for characters which invoke auto-filling.
529 Such characters have value t in this table.
530 */);
531   Vauto_fill_chars = Fmake_char_table (Qgeneric);
532 #ifdef UTF2000
533   put_char_id_table_0 (XCHAR_TABLE (Vauto_fill_chars), ' ', Qt);
534   put_char_id_table_0 (XCHAR_TABLE (Vauto_fill_chars), '\n', Qt);
535 #else
536   XCHAR_TABLE (Vauto_fill_chars)->ascii[' '] = Qt;
537   XCHAR_TABLE (Vauto_fill_chars)->ascii['\n'] = Qt;
538 #endif
539 }