* lisp/calendar/diary-lib.el (diary-remind): Fix bug#30455.
[emacs.git] / src / cmds.c
blob96b712ed6d2bff248bd0bae9b506d3479ed18588
1 /* Simple built-in editing commands.
3 Copyright (C) 1985, 1993-1998, 2001-2018 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or (at
10 your option) any later version.
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
21 #include <config.h>
23 #include "lisp.h"
24 #include "commands.h"
25 #include "character.h"
26 #include "buffer.h"
27 #include "syntax.h"
28 #include "keyboard.h"
29 #include "keymap.h"
30 #include "frame.h"
32 static int internal_self_insert (int, EMACS_INT);
34 DEFUN ("forward-point", Fforward_point, Sforward_point, 1, 1, 0,
35 doc: /* Return buffer position N characters after (before if N negative) point. */)
36 (Lisp_Object n)
38 CHECK_NUMBER (n);
40 return make_number (PT + XINT (n));
43 /* Add N to point; or subtract N if FORWARD is false. N defaults to 1.
44 Validate the new location. Return nil. */
45 static Lisp_Object
46 move_point (Lisp_Object n, bool forward)
48 /* This used to just set point to point + XINT (n), and then check
49 to see if it was within boundaries. But now that SET_PT can
50 potentially do a lot of stuff (calling entering and exiting
51 hooks, etcetera), that's not a good approach. So we validate the
52 proposed position, then set point. */
54 EMACS_INT new_point;
56 if (NILP (n))
57 XSETFASTINT (n, 1);
58 else
59 CHECK_NUMBER (n);
61 new_point = PT + (forward ? XINT (n) : - XINT (n));
63 if (new_point < BEGV)
65 SET_PT (BEGV);
66 xsignal0 (Qbeginning_of_buffer);
68 if (new_point > ZV)
70 SET_PT (ZV);
71 xsignal0 (Qend_of_buffer);
74 SET_PT (new_point);
75 return Qnil;
78 DEFUN ("forward-char", Fforward_char, Sforward_char, 0, 1, "^p",
79 doc: /* Move point N characters forward (backward if N is negative).
80 On reaching end or beginning of buffer, stop and signal error.
81 Interactively, N is the numeric prefix argument.
82 If N is omitted or nil, move point 1 character forward.
84 Depending on the bidirectional context, the movement may be to the
85 right or to the left on the screen. This is in contrast with
86 \\[right-char], which see. */)
87 (Lisp_Object n)
89 return move_point (n, 1);
92 DEFUN ("backward-char", Fbackward_char, Sbackward_char, 0, 1, "^p",
93 doc: /* Move point N characters backward (forward if N is negative).
94 On attempt to pass beginning or end of buffer, stop and signal error.
95 Interactively, N is the numeric prefix argument.
96 If N is omitted or nil, move point 1 character backward.
98 Depending on the bidirectional context, the movement may be to the
99 right or to the left on the screen. This is in contrast with
100 \\[left-char], which see. */)
101 (Lisp_Object n)
103 return move_point (n, 0);
106 DEFUN ("forward-line", Fforward_line, Sforward_line, 0, 1, "^p",
107 doc: /* Move N lines forward (backward if N is negative).
108 Precisely, if point is on line I, move to the start of line I + N
109 \("start of line" in the logical order).
110 If there isn't room, go as far as possible (no error).
112 Returns the count of lines left to move. If moving forward,
113 that is N minus number of lines moved; if backward, N plus number
114 moved.
116 Exception: With positive N, a non-empty line at the end of the
117 buffer, or of its accessible portion, counts as one line
118 successfully moved (for the return value). This means that the
119 function will move point to the end of such a line and will count
120 it as a line moved across, even though there is no next line to
121 go to its beginning. */)
122 (Lisp_Object n)
124 ptrdiff_t opoint = PT, pos, pos_byte, shortage, count;
126 if (NILP (n))
127 count = 1;
128 else
130 CHECK_NUMBER (n);
131 count = XINT (n);
134 shortage = scan_newline_from_point (count, &pos, &pos_byte);
136 SET_PT_BOTH (pos, pos_byte);
138 if (shortage > 0
139 && (count <= 0
140 || (ZV > BEGV
141 && PT != opoint
142 && (FETCH_BYTE (PT_BYTE - 1) != '\n'))))
143 shortage--;
145 return make_number (count <= 0 ? - shortage : shortage);
148 DEFUN ("beginning-of-line", Fbeginning_of_line, Sbeginning_of_line, 0, 1, "^p",
149 doc: /* Move point to beginning of current line (in the logical order).
150 With argument N not nil or 1, move forward N - 1 lines first.
151 If point reaches the beginning or end of buffer, it stops there.
153 This function constrains point to the current field unless this moves
154 point to a different line than the original, unconstrained result.
155 If N is nil or 1, and a front-sticky field starts at point, the point
156 does not move. To ignore field boundaries bind
157 `inhibit-field-text-motion' to t, or use the `forward-line' function
158 instead. For instance, `(forward-line 0)' does the same thing as
159 `(beginning-of-line)', except that it ignores field boundaries. */)
160 (Lisp_Object n)
162 if (NILP (n))
163 XSETFASTINT (n, 1);
164 else
165 CHECK_NUMBER (n);
167 SET_PT (XINT (Fline_beginning_position (n)));
169 return Qnil;
172 DEFUN ("end-of-line", Fend_of_line, Send_of_line, 0, 1, "^p",
173 doc: /* Move point to end of current line (in the logical order).
174 With argument N not nil or 1, move forward N - 1 lines first.
175 If point reaches the beginning or end of buffer, it stops there.
176 To ignore intangibility, bind `inhibit-point-motion-hooks' to t.
178 This function constrains point to the current field unless this moves
179 point to a different line than the original, unconstrained result. If
180 N is nil or 1, and a rear-sticky field ends at point, the point does
181 not move. To ignore field boundaries bind `inhibit-field-text-motion'
182 to t. */)
183 (Lisp_Object n)
185 ptrdiff_t newpos;
187 if (NILP (n))
188 XSETFASTINT (n, 1);
189 else
190 CHECK_NUMBER (n);
192 while (1)
194 newpos = XINT (Fline_end_position (n));
195 SET_PT (newpos);
197 if (PT > newpos
198 && FETCH_CHAR (PT - 1) == '\n')
200 /* If we skipped over a newline that follows
201 an invisible intangible run,
202 move back to the last tangible position
203 within the line. */
205 SET_PT (PT - 1);
206 break;
208 else if (PT > newpos && PT < ZV
209 && FETCH_CHAR (PT) != '\n')
210 /* If we skipped something intangible
211 and now we're not really at eol,
212 keep going. */
213 n = make_number (1);
214 else
215 break;
218 return Qnil;
221 DEFUN ("delete-char", Fdelete_char, Sdelete_char, 1, 2, "p\nP",
222 doc: /* Delete the following N characters (previous if N is negative).
223 Optional second arg KILLFLAG non-nil means kill instead (save in kill ring).
224 Interactively, N is the prefix arg, and KILLFLAG is set if
225 N was explicitly specified.
227 The command `delete-forward-char' is preferable for interactive use, e.g.
228 because it respects values of `delete-active-region' and `overwrite-mode'. */)
229 (Lisp_Object n, Lisp_Object killflag)
231 EMACS_INT pos;
233 CHECK_NUMBER (n);
235 if (eabs (XINT (n)) < 2)
236 call0 (Qundo_auto_amalgamate);
238 pos = PT + XINT (n);
239 if (NILP (killflag))
241 if (XINT (n) < 0)
243 if (pos < BEGV)
244 xsignal0 (Qbeginning_of_buffer);
245 else
246 del_range (pos, PT);
248 else
250 if (pos > ZV)
251 xsignal0 (Qend_of_buffer);
252 else
253 del_range (PT, pos);
256 else
258 call1 (Qkill_forward_chars, n);
260 return Qnil;
263 /* Note that there's code in command_loop_1 which typically avoids
264 calling this. */
265 DEFUN ("self-insert-command", Fself_insert_command, Sself_insert_command, 1, 1, "p",
266 doc: /* Insert the character you type.
267 Whichever character you type to run this command is inserted.
268 The numeric prefix argument N says how many times to repeat the insertion.
269 Before insertion, `expand-abbrev' is executed if the inserted character does
270 not have word syntax and the previous character in the buffer does.
271 After insertion, `internal-auto-fill' is called if
272 `auto-fill-function' is non-nil and if the `auto-fill-chars' table has
273 a non-nil value for the inserted character. At the end, it runs
274 `post-self-insert-hook'. */)
275 (Lisp_Object n)
277 CHECK_NUMBER (n);
279 if (XINT (n) < 0)
280 error ("Negative repetition argument %"pI"d", XINT (n));
282 if (XFASTINT (n) < 2)
283 call0 (Qundo_auto_amalgamate);
285 /* Barf if the key that invoked this was not a character. */
286 if (!CHARACTERP (last_command_event))
287 bitch_at_user ();
288 else {
289 int character = translate_char (Vtranslation_table_for_input,
290 XINT (last_command_event));
291 int val = internal_self_insert (character, XFASTINT (n));
292 if (val == 2)
293 Fset (Qundo_auto__this_command_amalgamating, Qnil);
294 frame_make_pointer_invisible (SELECTED_FRAME ());
297 return Qnil;
300 /* Insert N times character C
302 If this insertion is suitable for direct output (completely simple),
303 return 0. A value of 1 indicates this *might* not have been simple.
304 A value of 2 means this did things that call for an undo boundary. */
306 static int
307 internal_self_insert (int c, EMACS_INT n)
309 int hairy = 0;
310 Lisp_Object tem;
311 register enum syntaxcode synt;
312 Lisp_Object overwrite;
313 /* Length of multi-byte form of C. */
314 int len;
315 /* Working buffer and pointer for multi-byte form of C. */
316 unsigned char str[MAX_MULTIBYTE_LENGTH];
317 ptrdiff_t chars_to_delete = 0;
318 ptrdiff_t spaces_to_insert = 0;
320 overwrite = BVAR (current_buffer, overwrite_mode);
321 if (!NILP (Vbefore_change_functions) || !NILP (Vafter_change_functions))
322 hairy = 1;
324 /* At first, get multi-byte form of C in STR. */
325 if (!NILP (BVAR (current_buffer, enable_multibyte_characters)))
327 len = CHAR_STRING (c, str);
328 if (len == 1)
329 /* If C has modifier bits, this makes C an appropriate
330 one-byte char. */
331 c = *str;
333 else
335 str[0] = SINGLE_BYTE_CHAR_P (c) ? c : CHAR_TO_BYTE8 (c);
336 len = 1;
338 if (!NILP (overwrite)
339 && PT < ZV)
341 /* In overwrite-mode, we substitute a character at point (C2,
342 hereafter) by C. For that, we delete C2 in advance. But,
343 just substituting C2 by C may move a remaining text in the
344 line to the right or to the left, which is not preferable.
345 So we insert more spaces or delete more characters in the
346 following cases: if C is narrower than C2, after deleting C2,
347 we fill columns with spaces, if C is wider than C2, we delete
348 C2 and several characters following C2. */
350 /* This is the character after point. */
351 int c2 = FETCH_CHAR (PT_BYTE);
353 int cwidth;
355 /* Overwriting in binary-mode always replaces C2 by C.
356 Overwriting in textual-mode doesn't always do that.
357 It inserts newlines in the usual way,
358 and inserts any character at end of line
359 or before a tab if it doesn't use the whole width of the tab. */
360 if (EQ (overwrite, Qoverwrite_mode_binary))
361 chars_to_delete = min (n, PTRDIFF_MAX);
362 else if (c != '\n' && c2 != '\n'
363 && (cwidth = XFASTINT (Fchar_width (make_number (c)))) != 0)
365 ptrdiff_t pos = PT;
366 ptrdiff_t pos_byte = PT_BYTE;
367 ptrdiff_t curcol = current_column ();
369 if (n <= (min (MOST_POSITIVE_FIXNUM, PTRDIFF_MAX) - curcol) / cwidth)
371 /* Column the cursor should be placed at after this insertion.
372 The value should be calculated only when necessary. */
373 ptrdiff_t target_clm = curcol + n * cwidth;
375 /* The actual cursor position after the trial of moving
376 to column TARGET_CLM. It is greater than TARGET_CLM
377 if the TARGET_CLM is middle of multi-column
378 character. In that case, the new point is set after
379 that character. */
380 ptrdiff_t actual_clm
381 = XFASTINT (Fmove_to_column (make_number (target_clm), Qnil));
383 chars_to_delete = PT - pos;
385 if (actual_clm > target_clm)
387 /* We will delete too many columns. Let's fill columns
388 by spaces so that the remaining text won't move. */
389 ptrdiff_t actual = PT_BYTE;
390 DEC_POS (actual);
391 if (FETCH_CHAR (actual) == '\t')
392 /* Rather than add spaces, let's just keep the tab. */
393 chars_to_delete--;
394 else
395 spaces_to_insert = actual_clm - target_clm;
398 SET_PT_BOTH (pos, pos_byte);
401 hairy = 2;
404 synt = SYNTAX (c);
406 if (!NILP (BVAR (current_buffer, abbrev_mode))
407 && synt != Sword
408 && NILP (BVAR (current_buffer, read_only))
409 && PT > BEGV
410 && (SYNTAX (!NILP (BVAR (current_buffer, enable_multibyte_characters))
411 ? XFASTINT (Fprevious_char ())
412 : UNIBYTE_TO_CHAR (XFASTINT (Fprevious_char ())))
413 == Sword))
415 EMACS_INT modiff = MODIFF;
416 Lisp_Object sym;
418 sym = call0 (Qexpand_abbrev);
420 /* If we expanded an abbrev which has a hook,
421 and the hook has a non-nil `no-self-insert' property,
422 return right away--don't really self-insert. */
423 if (SYMBOLP (sym) && ! NILP (sym)
424 && ! NILP (XSYMBOL (sym)->u.s.function)
425 && SYMBOLP (XSYMBOL (sym)->u.s.function))
427 Lisp_Object prop;
428 prop = Fget (XSYMBOL (sym)->u.s.function, intern ("no-self-insert"));
429 if (! NILP (prop))
430 return 1;
433 if (MODIFF != modiff)
434 hairy = 2;
437 if (chars_to_delete)
439 int mc = ((NILP (BVAR (current_buffer, enable_multibyte_characters))
440 && SINGLE_BYTE_CHAR_P (c))
441 ? UNIBYTE_TO_CHAR (c) : c);
442 Lisp_Object string = Fmake_string (make_number (n), make_number (mc),
443 Qnil);
445 if (spaces_to_insert)
447 tem = Fmake_string (make_number (spaces_to_insert),
448 make_number (' '), Qnil);
449 string = concat2 (string, tem);
452 replace_range (PT, PT + chars_to_delete, string, 1, 1, 1, 0);
453 Fforward_char (make_number (n));
455 else if (n > 1)
457 USE_SAFE_ALLOCA;
458 char *strn, *p;
459 SAFE_NALLOCA (strn, len, n);
460 for (p = strn; n > 0; n--, p += len)
461 memcpy (p, str, len);
462 insert_and_inherit (strn, p - strn);
463 SAFE_FREE ();
465 else if (n > 0)
466 insert_and_inherit ((char *) str, len);
468 if ((CHAR_TABLE_P (Vauto_fill_chars)
469 ? !NILP (CHAR_TABLE_REF (Vauto_fill_chars, c))
470 : (c == ' ' || c == '\n'))
471 && !NILP (BVAR (current_buffer, auto_fill_function)))
473 Lisp_Object auto_fill_result;
475 if (c == '\n')
476 /* After inserting a newline, move to previous line and fill
477 that. Must have the newline in place already so filling and
478 justification, if any, know where the end is going to be. */
479 SET_PT_BOTH (PT - 1, PT_BYTE - 1);
480 auto_fill_result = call0 (Qinternal_auto_fill);
481 /* Test PT < ZV in case the auto-fill-function is strange. */
482 if (c == '\n' && PT < ZV)
483 SET_PT_BOTH (PT + 1, PT_BYTE + 1);
484 if (!NILP (auto_fill_result))
485 hairy = 2;
488 /* Run hooks for electric keys. */
489 run_hook (Qpost_self_insert_hook);
491 return hairy;
494 /* module initialization */
496 void
497 syms_of_cmds (void)
499 DEFSYM (Qinternal_auto_fill, "internal-auto-fill");
501 DEFSYM (Qundo_auto_amalgamate, "undo-auto-amalgamate");
502 DEFSYM (Qundo_auto__this_command_amalgamating,
503 "undo-auto--this-command-amalgamating");
505 DEFSYM (Qkill_forward_chars, "kill-forward-chars");
507 /* A possible value for a buffer's overwrite-mode variable. */
508 DEFSYM (Qoverwrite_mode_binary, "overwrite-mode-binary");
510 DEFSYM (Qexpand_abbrev, "expand-abbrev");
511 DEFSYM (Qpost_self_insert_hook, "post-self-insert-hook");
513 DEFVAR_LISP ("post-self-insert-hook", Vpost_self_insert_hook,
514 doc: /* Hook run at the end of `self-insert-command'.
515 This is run after inserting the character. */);
516 Vpost_self_insert_hook = Qnil;
518 defsubr (&Sforward_point);
519 defsubr (&Sforward_char);
520 defsubr (&Sbackward_char);
521 defsubr (&Sforward_line);
522 defsubr (&Sbeginning_of_line);
523 defsubr (&Send_of_line);
525 defsubr (&Sdelete_char);
526 defsubr (&Sself_insert_command);
529 void
530 keys_of_cmds (void)
532 int n;
534 initial_define_key (global_map, Ctl ('I'), "self-insert-command");
535 for (n = 040; n < 0177; n++)
536 initial_define_key (global_map, n, "self-insert-command");
537 #ifdef MSDOS
538 for (n = 0200; n < 0240; n++)
539 initial_define_key (global_map, n, "self-insert-command");
540 #endif
541 for (n = 0240; n < 0400; n++)
542 initial_define_key (global_map, n, "self-insert-command");
544 initial_define_key (global_map, Ctl ('A'), "beginning-of-line");
545 initial_define_key (global_map, Ctl ('B'), "backward-char");
546 initial_define_key (global_map, Ctl ('E'), "end-of-line");
547 initial_define_key (global_map, Ctl ('F'), "forward-char");