Fix minor problems with loaddefs autogeneration
[emacs.git] / src / cmds.c
blob51652d542a8cdb8652cfa31737c4c945adcf4734
1 /* Simple built-in editing commands.
3 Copyright (C) 1985, 1993-1998, 2001-2017 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 <http://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, the value of `auto-fill-function' is called if the
272 `auto-fill-chars' table has a non-nil value for the inserted character.
273 At the end, it runs `post-self-insert-hook'. */)
274 (Lisp_Object n)
276 CHECK_NUMBER (n);
278 if (XINT (n) < 0)
279 error ("Negative repetition argument %"pI"d", XINT (n));
281 if (XFASTINT (n) < 2)
282 call0 (Qundo_auto_amalgamate);
284 /* Barf if the key that invoked this was not a character. */
285 if (!CHARACTERP (last_command_event))
286 bitch_at_user ();
287 else {
288 int character = translate_char (Vtranslation_table_for_input,
289 XINT (last_command_event));
290 int val = internal_self_insert (character, XFASTINT (n));
291 if (val == 2)
292 Fset (Qundo_auto__this_command_amalgamating, Qnil);
293 frame_make_pointer_invisible (SELECTED_FRAME ());
296 return Qnil;
299 /* Insert N times character C
301 If this insertion is suitable for direct output (completely simple),
302 return 0. A value of 1 indicates this *might* not have been simple.
303 A value of 2 means this did things that call for an undo boundary. */
305 static int
306 internal_self_insert (int c, EMACS_INT n)
308 int hairy = 0;
309 Lisp_Object tem;
310 register enum syntaxcode synt;
311 Lisp_Object overwrite;
312 /* Length of multi-byte form of C. */
313 int len;
314 /* Working buffer and pointer for multi-byte form of C. */
315 unsigned char str[MAX_MULTIBYTE_LENGTH];
316 ptrdiff_t chars_to_delete = 0;
317 ptrdiff_t spaces_to_insert = 0;
319 overwrite = BVAR (current_buffer, overwrite_mode);
320 if (!NILP (Vbefore_change_functions) || !NILP (Vafter_change_functions))
321 hairy = 1;
323 /* At first, get multi-byte form of C in STR. */
324 if (!NILP (BVAR (current_buffer, enable_multibyte_characters)))
326 len = CHAR_STRING (c, str);
327 if (len == 1)
328 /* If C has modifier bits, this makes C an appropriate
329 one-byte char. */
330 c = *str;
332 else
334 str[0] = SINGLE_BYTE_CHAR_P (c) ? c : CHAR_TO_BYTE8 (c);
335 len = 1;
337 if (!NILP (overwrite)
338 && PT < ZV)
340 /* In overwrite-mode, we substitute a character at point (C2,
341 hereafter) by C. For that, we delete C2 in advance. But,
342 just substituting C2 by C may move a remaining text in the
343 line to the right or to the left, which is not preferable.
344 So we insert more spaces or delete more characters in the
345 following cases: if C is narrower than C2, after deleting C2,
346 we fill columns with spaces, if C is wider than C2, we delete
347 C2 and several characters following C2. */
349 /* This is the character after point. */
350 int c2 = FETCH_CHAR (PT_BYTE);
352 int cwidth;
354 /* Overwriting in binary-mode always replaces C2 by C.
355 Overwriting in textual-mode doesn't always do that.
356 It inserts newlines in the usual way,
357 and inserts any character at end of line
358 or before a tab if it doesn't use the whole width of the tab. */
359 if (EQ (overwrite, Qoverwrite_mode_binary))
360 chars_to_delete = min (n, PTRDIFF_MAX);
361 else if (c != '\n' && c2 != '\n'
362 && (cwidth = XFASTINT (Fchar_width (make_number (c)))) != 0)
364 ptrdiff_t pos = PT;
365 ptrdiff_t pos_byte = PT_BYTE;
366 ptrdiff_t curcol = current_column ();
368 if (n <= (min (MOST_POSITIVE_FIXNUM, PTRDIFF_MAX) - curcol) / cwidth)
370 /* Column the cursor should be placed at after this insertion.
371 The value should be calculated only when necessary. */
372 ptrdiff_t target_clm = curcol + n * cwidth;
374 /* The actual cursor position after the trial of moving
375 to column TARGET_CLM. It is greater than TARGET_CLM
376 if the TARGET_CLM is middle of multi-column
377 character. In that case, the new point is set after
378 that character. */
379 ptrdiff_t actual_clm
380 = XFASTINT (Fmove_to_column (make_number (target_clm), Qnil));
382 chars_to_delete = PT - pos;
384 if (actual_clm > target_clm)
386 /* We will delete too many columns. Let's fill columns
387 by spaces so that the remaining text won't move. */
388 ptrdiff_t actual = PT_BYTE;
389 DEC_POS (actual);
390 if (FETCH_CHAR (actual) == '\t')
391 /* Rather than add spaces, let's just keep the tab. */
392 chars_to_delete--;
393 else
394 spaces_to_insert = actual_clm - target_clm;
397 SET_PT_BOTH (pos, pos_byte);
400 hairy = 2;
403 synt = SYNTAX (c);
405 if (!NILP (BVAR (current_buffer, abbrev_mode))
406 && synt != Sword
407 && NILP (BVAR (current_buffer, read_only))
408 && PT > BEGV
409 && (SYNTAX (!NILP (BVAR (current_buffer, enable_multibyte_characters))
410 ? XFASTINT (Fprevious_char ())
411 : UNIBYTE_TO_CHAR (XFASTINT (Fprevious_char ())))
412 == Sword))
414 EMACS_INT modiff = MODIFF;
415 Lisp_Object sym;
417 sym = call0 (Qexpand_abbrev);
419 /* If we expanded an abbrev which has a hook,
420 and the hook has a non-nil `no-self-insert' property,
421 return right away--don't really self-insert. */
422 if (SYMBOLP (sym) && ! NILP (sym)
423 && ! NILP (XSYMBOL (sym)->function)
424 && SYMBOLP (XSYMBOL (sym)->function))
426 Lisp_Object prop;
427 prop = Fget (XSYMBOL (sym)->function, intern ("no-self-insert"));
428 if (! NILP (prop))
429 return 1;
432 if (MODIFF != modiff)
433 hairy = 2;
436 if (chars_to_delete)
438 int mc = ((NILP (BVAR (current_buffer, enable_multibyte_characters))
439 && SINGLE_BYTE_CHAR_P (c))
440 ? UNIBYTE_TO_CHAR (c) : c);
441 Lisp_Object string = Fmake_string (make_number (n), make_number (mc));
443 if (spaces_to_insert)
445 tem = Fmake_string (make_number (spaces_to_insert),
446 make_number (' '));
447 string = concat2 (string, tem);
450 replace_range (PT, PT + chars_to_delete, string, 1, 1, 1, 0);
451 Fforward_char (make_number (n));
453 else if (n > 1)
455 USE_SAFE_ALLOCA;
456 char *strn, *p;
457 SAFE_NALLOCA (strn, len, n);
458 for (p = strn; n > 0; n--, p += len)
459 memcpy (p, str, len);
460 insert_and_inherit (strn, p - strn);
461 SAFE_FREE ();
463 else if (n > 0)
464 insert_and_inherit ((char *) str, len);
466 if ((CHAR_TABLE_P (Vauto_fill_chars)
467 ? !NILP (CHAR_TABLE_REF (Vauto_fill_chars, c))
468 : (c == ' ' || c == '\n'))
469 && !NILP (BVAR (current_buffer, auto_fill_function)))
471 Lisp_Object auto_fill_result;
473 if (c == '\n')
474 /* After inserting a newline, move to previous line and fill
475 that. Must have the newline in place already so filling and
476 justification, if any, know where the end is going to be. */
477 SET_PT_BOTH (PT - 1, PT_BYTE - 1);
478 auto_fill_result = call0 (BVAR (current_buffer, auto_fill_function));
479 /* Test PT < ZV in case the auto-fill-function is strange. */
480 if (c == '\n' && PT < ZV)
481 SET_PT_BOTH (PT + 1, PT_BYTE + 1);
482 if (!NILP (auto_fill_result))
483 hairy = 2;
486 /* Run hooks for electric keys. */
487 run_hook (Qpost_self_insert_hook);
489 return hairy;
492 /* module initialization */
494 void
495 syms_of_cmds (void)
497 DEFSYM (Qundo_auto_amalgamate, "undo-auto-amalgamate");
498 DEFSYM (Qundo_auto__this_command_amalgamating,
499 "undo-auto--this-command-amalgamating");
501 DEFSYM (Qkill_forward_chars, "kill-forward-chars");
503 /* A possible value for a buffer's overwrite-mode variable. */
504 DEFSYM (Qoverwrite_mode_binary, "overwrite-mode-binary");
506 DEFSYM (Qexpand_abbrev, "expand-abbrev");
507 DEFSYM (Qpost_self_insert_hook, "post-self-insert-hook");
509 DEFVAR_LISP ("post-self-insert-hook", Vpost_self_insert_hook,
510 doc: /* Hook run at the end of `self-insert-command'.
511 This is run after inserting the character. */);
512 Vpost_self_insert_hook = Qnil;
514 defsubr (&Sforward_point);
515 defsubr (&Sforward_char);
516 defsubr (&Sbackward_char);
517 defsubr (&Sforward_line);
518 defsubr (&Sbeginning_of_line);
519 defsubr (&Send_of_line);
521 defsubr (&Sdelete_char);
522 defsubr (&Sself_insert_command);
525 void
526 keys_of_cmds (void)
528 int n;
530 initial_define_key (global_map, Ctl ('I'), "self-insert-command");
531 for (n = 040; n < 0177; n++)
532 initial_define_key (global_map, n, "self-insert-command");
533 #ifdef MSDOS
534 for (n = 0200; n < 0240; n++)
535 initial_define_key (global_map, n, "self-insert-command");
536 #endif
537 for (n = 0240; n < 0400; n++)
538 initial_define_key (global_map, n, "self-insert-command");
540 initial_define_key (global_map, Ctl ('A'), "beginning-of-line");
541 initial_define_key (global_map, Ctl ('B'), "backward-char");
542 initial_define_key (global_map, Ctl ('E'), "end-of-line");
543 initial_define_key (global_map, Ctl ('F'), "forward-char");