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/>. */
25 #include "character.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. */)
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. */
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. */
61 new_point
= PT
+ (forward
? XINT (n
) : - XINT (n
));
66 xsignal0 (Qbeginning_of_buffer
);
71 xsignal0 (Qend_of_buffer
);
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. */)
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. */)
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
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. */)
124 ptrdiff_t opoint
= PT
, pos
, pos_byte
, shortage
, count
;
134 shortage
= scan_newline_from_point (count
, &pos
, &pos_byte
);
136 SET_PT_BOTH (pos
, pos_byte
);
142 && (FETCH_BYTE (PT_BYTE
- 1) != '\n'))))
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. */)
167 SET_PT (XINT (Fline_beginning_position (n
)));
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'
194 newpos
= XINT (Fline_end_position (n
));
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
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,
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
)
235 if (eabs (XINT (n
)) < 2)
236 call0 (Qundo_auto_amalgamate
);
244 xsignal0 (Qbeginning_of_buffer
);
251 xsignal0 (Qend_of_buffer
);
258 call1 (Qkill_forward_chars
, n
);
263 /* Note that there's code in command_loop_1 which typically avoids
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'. */)
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
))
289 int character
= translate_char (Vtranslation_table_for_input
,
290 XINT (last_command_event
));
291 int val
= internal_self_insert (character
, XFASTINT (n
));
293 Fset (Qundo_auto__this_command_amalgamating
, Qnil
);
294 frame_make_pointer_invisible (SELECTED_FRAME ());
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. */
307 internal_self_insert (int c
, EMACS_INT n
)
311 register enum syntaxcode synt
;
312 Lisp_Object overwrite
;
313 /* Length of multi-byte form of C. */
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
))
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
);
329 /* If C has modifier bits, this makes C an appropriate
335 str
[0] = SINGLE_BYTE_CHAR_P (c
) ? c
: CHAR_TO_BYTE8 (c
);
338 if (!NILP (overwrite
)
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
);
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)
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
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
;
391 if (FETCH_CHAR (actual
) == '\t')
392 /* Rather than add spaces, let's just keep the tab. */
395 spaces_to_insert
= actual_clm
- target_clm
;
398 SET_PT_BOTH (pos
, pos_byte
);
406 if (!NILP (BVAR (current_buffer
, abbrev_mode
))
408 && NILP (BVAR (current_buffer
, read_only
))
410 && (SYNTAX (!NILP (BVAR (current_buffer
, enable_multibyte_characters
))
411 ? XFASTINT (Fprevious_char ())
412 : UNIBYTE_TO_CHAR (XFASTINT (Fprevious_char ())))
415 EMACS_INT modiff
= MODIFF
;
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
))
428 prop
= Fget (XSYMBOL (sym
)->u
.s
.function
, intern ("no-self-insert"));
433 if (MODIFF
!= modiff
)
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
));
444 if (spaces_to_insert
)
446 tem
= Fmake_string (make_number (spaces_to_insert
),
448 string
= concat2 (string
, tem
);
451 replace_range (PT
, PT
+ chars_to_delete
, string
, 1, 1, 1, 0);
452 Fforward_char (make_number (n
));
458 SAFE_NALLOCA (strn
, len
, n
);
459 for (p
= strn
; n
> 0; n
--, p
+= len
)
460 memcpy (p
, str
, len
);
461 insert_and_inherit (strn
, p
- strn
);
465 insert_and_inherit ((char *) str
, len
);
467 if ((CHAR_TABLE_P (Vauto_fill_chars
)
468 ? !NILP (CHAR_TABLE_REF (Vauto_fill_chars
, c
))
469 : (c
== ' ' || c
== '\n'))
470 && !NILP (BVAR (current_buffer
, auto_fill_function
)))
472 Lisp_Object auto_fill_result
;
475 /* After inserting a newline, move to previous line and fill
476 that. Must have the newline in place already so filling and
477 justification, if any, know where the end is going to be. */
478 SET_PT_BOTH (PT
- 1, PT_BYTE
- 1);
479 auto_fill_result
= call0 (Qinternal_auto_fill
);
480 /* Test PT < ZV in case the auto-fill-function is strange. */
481 if (c
== '\n' && PT
< ZV
)
482 SET_PT_BOTH (PT
+ 1, PT_BYTE
+ 1);
483 if (!NILP (auto_fill_result
))
487 /* Run hooks for electric keys. */
488 run_hook (Qpost_self_insert_hook
);
493 /* module initialization */
498 DEFSYM (Qinternal_auto_fill
, "internal-auto-fill");
500 DEFSYM (Qundo_auto_amalgamate
, "undo-auto-amalgamate");
501 DEFSYM (Qundo_auto__this_command_amalgamating
,
502 "undo-auto--this-command-amalgamating");
504 DEFSYM (Qkill_forward_chars
, "kill-forward-chars");
506 /* A possible value for a buffer's overwrite-mode variable. */
507 DEFSYM (Qoverwrite_mode_binary
, "overwrite-mode-binary");
509 DEFSYM (Qexpand_abbrev
, "expand-abbrev");
510 DEFSYM (Qpost_self_insert_hook
, "post-self-insert-hook");
512 DEFVAR_LISP ("post-self-insert-hook", Vpost_self_insert_hook
,
513 doc
: /* Hook run at the end of `self-insert-command'.
514 This is run after inserting the character. */);
515 Vpost_self_insert_hook
= Qnil
;
517 defsubr (&Sforward_point
);
518 defsubr (&Sforward_char
);
519 defsubr (&Sbackward_char
);
520 defsubr (&Sforward_line
);
521 defsubr (&Sbeginning_of_line
);
522 defsubr (&Send_of_line
);
524 defsubr (&Sdelete_char
);
525 defsubr (&Sself_insert_command
);
533 initial_define_key (global_map
, Ctl ('I'), "self-insert-command");
534 for (n
= 040; n
< 0177; n
++)
535 initial_define_key (global_map
, n
, "self-insert-command");
537 for (n
= 0200; n
< 0240; n
++)
538 initial_define_key (global_map
, n
, "self-insert-command");
540 for (n
= 0240; n
< 0400; n
++)
541 initial_define_key (global_map
, n
, "self-insert-command");
543 initial_define_key (global_map
, Ctl ('A'), "beginning-of-line");
544 initial_define_key (global_map
, Ctl ('B'), "backward-char");
545 initial_define_key (global_map
, Ctl ('E'), "end-of-line");
546 initial_define_key (global_map
, Ctl ('F'), "forward-char");