(ediff-autostore-merges): Doc fix.
[bpt/emacs.git] / src / cmds.c
CommitLineData
cd645247 1/* Simple built-in editing commands.
4a2f9c6a 2 Copyright (C) 1985, 93, 94, 95, 96, 97, 1998 Free Software Foundation, Inc.
cd645247
JB
3
4This file is part of GNU Emacs.
5
6GNU Emacs is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
502ddf23 8the Free Software Foundation; either version 2, or (at your option)
cd645247
JB
9any later version.
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Emacs; see the file COPYING. If not, write to
3b7ad313
EN
18the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA. */
cd645247
JB
20
21
18160b98 22#include <config.h>
cd645247
JB
23#include "lisp.h"
24#include "commands.h"
25#include "buffer.h"
9e4fd67b 26#include "charset.h"
cd645247 27#include "syntax.h"
f109dfa2 28#include "window.h"
346e0c2d 29#include "keyboard.h"
cd645247
JB
30
31Lisp_Object Qkill_forward_chars, Qkill_backward_chars, Vblink_paren_function;
32
6bbb0d4a
JB
33/* A possible value for a buffer's overwrite-mode variable. */
34Lisp_Object Qoverwrite_mode_binary;
35
189fad68
RS
36/* Non-nil means put this face on the next self-inserting character. */
37Lisp_Object Vself_insert_face;
38
39/* This is the command that set up Vself_insert_face. */
40Lisp_Object Vself_insert_face_command;
41
189fad68 42extern Lisp_Object Qface;
cd645247 43\f
9e4fd67b
KH
44DEFUN ("forward-point", Fforward_point, Sforward_point, 1, 1, 0,
45 "Return buffer position N characters after (before if N negative) point.")
46 (n)
47 Lisp_Object n;
48{
49 CHECK_NUMBER (n, 0);
50
049749e6 51 return make_number (PT + XINT (n));
9e4fd67b
KH
52}
53
cd645247 54DEFUN ("forward-char", Fforward_char, Sforward_char, 0, 1, "p",
72d5f589 55 "Move point right N characters (left if N is negative).\n\
cd645247 56On reaching end of buffer, stop and signal error.")
72d5f589
EN
57 (n)
58 Lisp_Object n;
cd645247 59{
72d5f589
EN
60 if (NILP (n))
61 XSETFASTINT (n, 1);
cd645247 62 else
72d5f589 63 CHECK_NUMBER (n, 0);
cd645247 64
72d5f589 65 /* This used to just set point to point + XINT (n), and then check
7b502dc3
JB
66 to see if it was within boundaries. But now that SET_PT can
67 potentially do a lot of stuff (calling entering and exiting
68 hooks, etcetera), that's not a good approach. So we validate the
69 proposed position, then set point. */
70 {
049749e6 71 int new_point = PT + XINT (n);
7b502dc3
JB
72
73 if (new_point < BEGV)
74 {
75 SET_PT (BEGV);
76 Fsignal (Qbeginning_of_buffer, Qnil);
77 }
78 if (new_point > ZV)
79 {
80 SET_PT (ZV);
81 Fsignal (Qend_of_buffer, Qnil);
82 }
83
84 SET_PT (new_point);
85 }
86
cd645247
JB
87 return Qnil;
88}
89
90DEFUN ("backward-char", Fbackward_char, Sbackward_char, 0, 1, "p",
72d5f589 91 "Move point left N characters (right if N is negative).\n\
cd645247 92On attempt to pass beginning or end of buffer, stop and signal error.")
72d5f589
EN
93 (n)
94 Lisp_Object n;
cd645247 95{
72d5f589
EN
96 if (NILP (n))
97 XSETFASTINT (n, 1);
cd645247 98 else
72d5f589 99 CHECK_NUMBER (n, 0);
cd645247 100
72d5f589
EN
101 XSETINT (n, - XINT (n));
102 return Fforward_char (n);
cd645247
JB
103}
104
105DEFUN ("forward-line", Fforward_line, Sforward_line, 0, 1, "p",
72d5f589
EN
106 "Move N lines forward (backward if N is negative).\n\
107Precisely, if point is on line I, move to the start of line I + N.\n\
cd645247
JB
108If there isn't room, go as far as possible (no error).\n\
109Returns the count of lines left to move. If moving forward,\n\
72d5f589
EN
110that is N - number of lines moved; if backward, N + number moved.\n\
111With positive N, a non-empty line at the end counts as one line\n\
cd645247
JB
112 successfully moved (for the return value).")
113 (n)
114 Lisp_Object n;
115{
049749e6
RS
116 int opoint = PT, opoint_byte = PT_BYTE;
117 int pos, pos_byte;
118 int count, shortage;
119 int temp;
cd645247 120
265a9e55 121 if (NILP (n))
cd645247
JB
122 count = 1;
123 else
124 {
125 CHECK_NUMBER (n, 0);
126 count = XINT (n);
127 }
128
049749e6
RS
129 if (count <= 0)
130 shortage = scan_newline (PT, PT_BYTE, BEGV, BEGV_BYTE, count - 1, 1);
131 else
132 shortage = scan_newline (PT, PT_BYTE, ZV, ZV_BYTE, count, 1);
133
134 /* Since scan_newline does TEMP_SET_PT_BOTH,
135 and we want to set PT "for real",
136 go back to the old point and then come back here. */
137 pos = PT;
138 pos_byte = PT_BYTE;
139 TEMP_SET_PT_BOTH (opoint, opoint_byte);
140 SET_PT_BOTH (pos, pos_byte);
141
cd645247 142 if (shortage > 0
049749e6 143 && (count <= 0
502ddf23 144 || (ZV > BEGV
049749e6
RS
145 && PT != opoint
146 && (FETCH_BYTE (PT_BYTE - 1) != '\n'))))
cd645247 147 shortage--;
049749e6
RS
148
149 return make_number (count <= 0 ? - shortage : shortage);
cd645247
JB
150}
151
152DEFUN ("beginning-of-line", Fbeginning_of_line, Sbeginning_of_line,
153 0, 1, "p",
154 "Move point to beginning of current line.\n\
72d5f589 155With argument N not nil or 1, move forward N - 1 lines first.\n\
cd645247
JB
156If scan reaches end of buffer, stop there without error.")
157 (n)
158 Lisp_Object n;
159{
265a9e55 160 if (NILP (n))
48c7cef2 161 XSETFASTINT (n, 1);
cd645247
JB
162 else
163 CHECK_NUMBER (n, 0);
164
38b294ca 165 SET_PT (XINT (Fline_beginning_position (n)));
cd645247
JB
166 return Qnil;
167}
168
169DEFUN ("end-of-line", Fend_of_line, Send_of_line,
170 0, 1, "p",
171 "Move point to end of current line.\n\
72d5f589 172With argument N not nil or 1, move forward N - 1 lines first.\n\
cd645247
JB
173If scan reaches end of buffer, stop there without error.")
174 (n)
175 Lisp_Object n;
176{
177 register int pos;
178 register int stop;
179
265a9e55 180 if (NILP (n))
48c7cef2 181 XSETFASTINT (n, 1);
cd645247
JB
182 else
183 CHECK_NUMBER (n, 0);
184
38b294ca 185 SET_PT (XINT (Fline_end_position (n)));
cd645247
JB
186
187 return Qnil;
188}
189
190DEFUN ("delete-char", Fdelete_char, Sdelete_char, 1, 2, "p\nP",
72d5f589 191 "Delete the following N characters (previous if N is negative).\n\
cd645247 192Optional second arg KILLFLAG non-nil means kill instead (save in kill ring).\n\
72d5f589
EN
193Interactively, N is the prefix arg, and KILLFLAG is set if\n\
194N was explicitly specified.")
cd645247
JB
195 (n, killflag)
196 Lisp_Object n, killflag;
197{
9e4fd67b
KH
198 int pos;
199
cd645247
JB
200 CHECK_NUMBER (n, 0);
201
049749e6 202 pos = PT + XINT (n);
265a9e55 203 if (NILP (killflag))
cd645247
JB
204 {
205 if (XINT (n) < 0)
206 {
9e4fd67b 207 if (pos < BEGV)
cd645247
JB
208 Fsignal (Qbeginning_of_buffer, Qnil);
209 else
9e4fd67b 210 del_range (pos, PT);
cd645247
JB
211 }
212 else
213 {
9e4fd67b 214 if (pos > ZV)
cd645247
JB
215 Fsignal (Qend_of_buffer, Qnil);
216 else
9e4fd67b 217 del_range (PT, pos);
cd645247
JB
218 }
219 }
220 else
221 {
222 call1 (Qkill_forward_chars, n);
223 }
224 return Qnil;
225}
226
227DEFUN ("delete-backward-char", Fdelete_backward_char, Sdelete_backward_char,
228 1, 2, "p\nP",
72d5f589 229 "Delete the previous N characters (following if N is negative).\n\
cd645247 230Optional second arg KILLFLAG non-nil means kill instead (save in kill ring).\n\
72d5f589
EN
231Interactively, N is the prefix arg, and KILLFLAG is set if\n\
232N was explicitly specified.")
cd645247
JB
233 (n, killflag)
234 Lisp_Object n, killflag;
235{
aa970069 236 Lisp_Object value;
7c983171 237 int deleted_special = 0;
ceb7e4f8 238 int pos, pos_byte, i;
aa970069 239
cd645247 240 CHECK_NUMBER (n, 0);
aa970069 241
7c983171 242 /* See if we are about to delete a tab or newline backwards. */
ceb7e4f8
KH
243 pos = PT;
244 pos_byte = PT_BYTE;
245 for (i = 0; i < XINT (n) && pos_byte > BEGV_BYTE; i++)
aa970069 246 {
9e4fd67b
KH
247 int c;
248
ceb7e4f8
KH
249 DEC_BOTH (pos, pos_byte);
250 c = FETCH_BYTE (pos_byte);
9e4fd67b 251 if (c == '\t' || c == '\n')
aa970069 252 {
7c983171 253 deleted_special = 1;
aa970069
RS
254 break;
255 }
256 }
257
aa970069
RS
258 /* In overwrite mode, back over columns while clearing them out,
259 unless at end of line. */
260 if (XINT (n) > 0
261 && ! NILP (current_buffer->overwrite_mode)
7c983171 262 && ! deleted_special
049749e6 263 && ! (PT == ZV || FETCH_BYTE (PT_BYTE) == '\n'))
aa970069 264 {
9e4fd67b
KH
265 int column = current_column ();
266
267 value = Fdelete_char (make_number (-XINT (n)), killflag);
268 i = column - current_column ();
cac55749 269 Finsert_char (make_number (' '), make_number (i), Qnil);
049749e6
RS
270 /* Whitespace chars are ASCII chars, so we can simply subtract. */
271 SET_PT_BOTH (PT - i, PT_BYTE - i);
aa970069 272 }
9e4fd67b
KH
273 else
274 value = Fdelete_char (make_number (-XINT (n)), killflag);
aa970069
RS
275
276 return value;
cd645247
JB
277}
278
279DEFUN ("self-insert-command", Fself_insert_command, Sself_insert_command, 1, 1, "p",
280 "Insert the character you type.\n\
281Whichever character you type to run this command is inserted.")
72d5f589
EN
282 (n)
283 Lisp_Object n;
cd645247 284{
a22ca1e0
RS
285 int character = XINT (last_command_char);
286
72d5f589 287 CHECK_NUMBER (n, 0);
cd645247
JB
288
289 /* Barf if the key that invoked this was not a character. */
ed76f667 290 if (!INTEGERP (last_command_char))
cd645247 291 bitch_at_user ();
72d5f589 292 else if (XINT (n) >= 2 && NILP (current_buffer->overwrite_mode))
2718dfa4 293 {
a22ca1e0
RS
294 int modified_char = character;
295 /* Add the offset to the character, for Finsert_char.
296 We pass internal_self_insert the unmodified character
297 because it itself does this offsetting. */
49bc32b0
RS
298 if (! NILP (current_buffer->enable_multibyte_characters))
299 modified_char = unibyte_char_to_multibyte (modified_char);
a22ca1e0 300
72d5f589 301 XSETFASTINT (n, XFASTINT (n) - 2);
2718dfa4 302 /* The first one might want to expand an abbrev. */
a22ca1e0 303 internal_self_insert (character, 1);
2718dfa4
RS
304 /* The bulk of the copies of this char can be inserted simply.
305 We don't have to handle a user-specified face specially
306 because it will get inherited from the first char inserted. */
a22ca1e0 307 Finsert_char (make_number (modified_char), n, Qt);
2718dfa4 308 /* The last one might want to auto-fill. */
a22ca1e0 309 internal_self_insert (character, 0);
2718dfa4 310 }
cd645247 311 else
72d5f589 312 while (XINT (n) > 0)
cd645247 313 {
f58dd69b 314 /* Ok since old and new vals both nonneg */
72d5f589 315 XSETFASTINT (n, XFASTINT (n) - 1);
a22ca1e0 316 internal_self_insert (character, XFASTINT (n) != 0);
cd645247
JB
317 }
318
319 return Qnil;
320}
321
9e4fd67b 322/* Insert character C. If NOAUTOFILL is nonzero, don't do autofill
4c6e656f
RS
323 even if it is enabled.
324
325 If this insertion is suitable for direct output (completely simple),
aa52fef9
RS
326 return 0. A value of 1 indicates this *might* not have been simple.
327 A value of 2 means this did things that call for an undo boundary. */
4c6e656f 328
9e4fd67b
KH
329internal_self_insert (c, noautofill)
330 int c;
cd645247
JB
331 int noautofill;
332{
333 extern Lisp_Object Fexpand_abbrev ();
334 int hairy = 0;
335 Lisp_Object tem;
336 register enum syntaxcode synt;
e744155a 337 Lisp_Object overwrite, string;
9e4fd67b
KH
338 /* Length of multi-byte form of C. */
339 int len;
340 /* Working buffer and pointer for multi-byte form of C. */
341 unsigned char workbuf[4], *str;
049749e6 342 int chars_to_delete = 0;
e744155a 343 int spaces_to_insert = 0;
cd645247 344
e7aacab7 345 overwrite = current_buffer->overwrite_mode;
166a4263
RS
346 if (!NILP (Vbefore_change_function) || !NILP (Vafter_change_function)
347 || !NILP (Vbefore_change_functions) || !NILP (Vafter_change_functions))
cd645247
JB
348 hairy = 1;
349
9e4fd67b
KH
350 /* At first, get multi-byte form of C in STR. */
351 if (!NILP (current_buffer->enable_multibyte_characters))
b9859007
KH
352 {
353 c = unibyte_char_to_multibyte (c);
354 len = CHAR_STRING (c, workbuf, str);
355 }
9e4fd67b
KH
356 else
357 workbuf[0] = c, str = workbuf, len = 1;
358
6bbb0d4a 359 if (!NILP (overwrite)
9e4fd67b 360 && PT < ZV)
cd645247 361 {
9e4fd67b
KH
362 /* In overwrite-mode, we substitute a character at point (C2,
363 hereafter) by C. For that, we delete C2 in advance. But,
364 just substituting C2 by C may move a remaining text in the
365 line to the right or to the left, which is not preferable.
366 So we insert more spaces or delete more characters in the
367 following cases: if C is narrower than C2, after deleting C2,
368 we fill columns with spaces, if C is wider than C2, we delete
369 C2 and several characters following C2. */
370
216b9443
RS
371 /* This is the character after point. */
372 int c2 = FETCH_CHAR (PT_BYTE);
373
374 /* Column the cursor should be placed at after this insertion.
9e4fd67b
KH
375 The correct value should be calculated only when necessary. */
376 int target_clm = 0;
377
37c0ed09
RS
378 /* Overwriting in binary-mode always replaces C2 by C.
379 Overwriting in textual-mode doesn't always do that.
380 It inserts newlines in the usual way,
381 and inserts any character at end of line
382 or before a tab if it doesn't use the whole width of the tab. */
9e4fd67b
KH
383 if (EQ (overwrite, Qoverwrite_mode_binary)
384 || (c != '\n'
385 && c2 != '\n'
37c0ed09
RS
386 && ! (c2 == '\t'
387 && XINT (current_buffer->tab_width) > 0
388 && XFASTINT (current_buffer->tab_width) < 20
216b9443
RS
389 && (target_clm = (current_column ()
390 + XINT (Fchar_width (make_number (c2)))),
37c0ed09 391 target_clm % XFASTINT (current_buffer->tab_width)))))
9e4fd67b 392 {
e744155a 393 int pos = PT;
049749e6 394 int pos_byte = PT_BYTE;
e744155a 395
9e4fd67b 396 if (target_clm == 0)
049749e6 397 chars_to_delete = 1;
9e4fd67b
KH
398 else
399 {
9e4fd67b
KH
400 /* The actual cursor position after the trial of moving
401 to column TARGET_CLM. It is greater than TARGET_CLM
402 if the TARGET_CLM is middle of multi-column
403 character. In that case, the new point is set after
404 that character. */
cac55749
RS
405 int actual_clm
406 = XFASTINT (Fmove_to_column (make_number (target_clm), Qnil));
9e4fd67b 407
049749e6 408 chars_to_delete = PT - pos;
e744155a 409
9e4fd67b
KH
410 if (actual_clm > target_clm)
411 {
e744155a 412 /* We will delete too many columns. Let's fill columns
9e4fd67b 413 by spaces so that the remaining text won't move. */
e744155a 414 spaces_to_insert = actual_clm - target_clm;
9e4fd67b
KH
415 }
416 }
049749e6 417 SET_PT_BOTH (pos, pos_byte);
9e4fd67b
KH
418 hairy = 2;
419 }
aa52fef9 420 hairy = 2;
cd645247 421 }
265a9e55 422 if (!NILP (current_buffer->abbrev_mode)
cd645247 423 && SYNTAX (c) != Sword
265a9e55 424 && NILP (current_buffer->read_only)
9e4fd67b 425 && PT > BEGV && SYNTAX (XFASTINT (Fprevious_char ())) == Sword)
cd645247 426 {
ee8caabb 427 int modiff = MODIFF;
e57640c0
RS
428 Lisp_Object sym;
429
430 sym = Fexpand_abbrev ();
431
432 /* If we expanded an abbrev which has only a hook,
9317a902 433 and the hook has a non-nil `no-self-insert' property,
e57640c0 434 return right away--don't really self-insert. */
9317a902
RS
435 if (! NILP (sym) && ! NILP (XSYMBOL (sym)->function)
436 && SYMBOLP (XSYMBOL (sym)->function))
e57640c0
RS
437 {
438 Lisp_Object prop;
9317a902 439 prop = Fget (XSYMBOL (sym)->function, intern ("no-self-insert"));
e57640c0 440 if (! NILP (prop))
6787d111 441 return 1;
e57640c0
RS
442 }
443
ee8caabb 444 if (MODIFF != modiff)
aa52fef9 445 hairy = 2;
cd645247 446 }
e744155a 447
049749e6 448 if (chars_to_delete)
e744155a 449 {
f34206b4 450 string = make_string_from_bytes (str, 1, len);
e744155a
RS
451 if (spaces_to_insert)
452 {
453 tem = Fmake_string (make_number (spaces_to_insert),
454 make_number (' '));
455 string = concat2 (tem, string);
456 }
457
aab28f47 458 replace_range (PT, PT + chars_to_delete, string, 1, 1, 0);
1bf95511 459 Fforward_char (make_number (1 + spaces_to_insert));
e744155a
RS
460 }
461 else
462 insert_and_inherit (str, len);
463
cd645247
JB
464 if ((c == ' ' || c == '\n')
465 && !noautofill
3de15b7a 466 && !NILP (current_buffer->auto_fill_function))
cd645247 467 {
76bb6dbb
KH
468 Lisp_Object tem;
469
9e4fd67b 470 if (c == '\n')
049749e6
RS
471 /* After inserting a newline, move to previous line and fill
472 that. Must have the newline in place already so filling and
473 justification, if any, know where the end is going to be. */
474 SET_PT_BOTH (PT - 1, PT_BYTE - 1);
76bb6dbb 475 tem = call0 (current_buffer->auto_fill_function);
9e4fd67b 476 if (c == '\n')
049749e6 477 SET_PT_BOTH (PT + 1, PT_BYTE + 1);
76bb6dbb
KH
478 if (!NILP (tem))
479 hairy = 2;
cd645247 480 }
189fad68 481
38d404db 482#ifdef HAVE_FACES
189fad68
RS
483 /* If previous command specified a face to use, use it. */
484 if (!NILP (Vself_insert_face)
346e0c2d 485 && EQ (current_kboard->Vlast_command, Vself_insert_face_command))
189fad68 486 {
049749e6
RS
487 Fput_text_property (make_number (PT - 1), make_number (PT),
488 Qface, Vself_insert_face, Qnil);
189fad68
RS
489 Vself_insert_face = Qnil;
490 }
38d404db 491#endif
e744155a 492
cd645247
JB
493 synt = SYNTAX (c);
494 if ((synt == Sclose || synt == Smath)
2718dfa4
RS
495 && !NILP (Vblink_paren_function) && INTERACTIVE
496 && !noautofill)
cd645247
JB
497 {
498 call0 (Vblink_paren_function);
aa52fef9 499 hairy = 2;
cd645247
JB
500 }
501 return hairy;
502}
503\f
504/* module initialization */
505
506syms_of_cmds ()
507{
508 Qkill_backward_chars = intern ("kill-backward-chars");
509 staticpro (&Qkill_backward_chars);
510
511 Qkill_forward_chars = intern ("kill-forward-chars");
512 staticpro (&Qkill_forward_chars);
513
6bbb0d4a
JB
514 Qoverwrite_mode_binary = intern ("overwrite-mode-binary");
515 staticpro (&Qoverwrite_mode_binary);
e686c647 516
189fad68
RS
517 DEFVAR_LISP ("self-insert-face", &Vself_insert_face,
518 "If non-nil, set the face of the next self-inserting character to this.\n\
519See also `self-insert-face-command'.");
520 Vself_insert_face = Qnil;
521
522 DEFVAR_LISP ("self-insert-face-command", &Vself_insert_face_command,
523 "This is the command that set up `self-insert-face'.\n\
524If `last-command' does not equal this value, we ignore `self-insert-face'.");
525 Vself_insert_face_command = Qnil;
526
cd645247
JB
527 DEFVAR_LISP ("blink-paren-function", &Vblink_paren_function,
528 "Function called, if non-nil, whenever a close parenthesis is inserted.\n\
529More precisely, a char with closeparen syntax is self-inserted.");
530 Vblink_paren_function = Qnil;
531
9e4fd67b 532 defsubr (&Sforward_point);
cd645247
JB
533 defsubr (&Sforward_char);
534 defsubr (&Sbackward_char);
535 defsubr (&Sforward_line);
536 defsubr (&Sbeginning_of_line);
537 defsubr (&Send_of_line);
538
539 defsubr (&Sdelete_char);
540 defsubr (&Sdelete_backward_char);
541
542 defsubr (&Sself_insert_command);
cd645247
JB
543}
544
545keys_of_cmds ()
546{
547 int n;
548
cbf65115 549 initial_define_key (global_map, Ctl ('I'), "self-insert-command");
cd645247
JB
550 for (n = 040; n < 0177; n++)
551 initial_define_key (global_map, n, "self-insert-command");
cf9cdc11
RS
552#ifdef MSDOS
553 for (n = 0200; n < 0240; n++)
554 initial_define_key (global_map, n, "self-insert-command");
555#endif
94748cb9 556 for (n = 0240; n < 0400; n++)
eb46da6a 557 initial_define_key (global_map, n, "self-insert-command");
cd645247
JB
558
559 initial_define_key (global_map, Ctl ('A'), "beginning-of-line");
560 initial_define_key (global_map, Ctl ('B'), "backward-char");
561 initial_define_key (global_map, Ctl ('D'), "delete-char");
562 initial_define_key (global_map, Ctl ('E'), "end-of-line");
563 initial_define_key (global_map, Ctl ('F'), "forward-char");
564 initial_define_key (global_map, 0177, "delete-backward-char");
565}