1 /* Simple built-in editing commands.
2 Copyright (C) 1985, 1993, 1994 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
28 Lisp_Object Qkill_forward_chars
, Qkill_backward_chars
, Vblink_paren_function
;
29 Lisp_Object Vuse_hard_newlines
;
31 /* A possible value for a buffer's overwrite-mode variable. */
32 Lisp_Object Qoverwrite_mode_binary
;
34 #ifdef USE_TEXT_PROPERTIES
39 DEFUN ("forward-char", Fforward_char
, Sforward_char
, 0, 1, "p",
40 "Move point right ARG characters (left if ARG negative).\n\
41 On reaching end of buffer, stop and signal error.")
50 /* This used to just set point to point + XINT (n), and then check
51 to see if it was within boundaries. But now that SET_PT can
52 potentially do a lot of stuff (calling entering and exiting
53 hooks, etcetera), that's not a good approach. So we validate the
54 proposed position, then set point. */
56 int new_point
= point
+ XINT (n
);
61 Fsignal (Qbeginning_of_buffer
, Qnil
);
66 Fsignal (Qend_of_buffer
, Qnil
);
75 DEFUN ("backward-char", Fbackward_char
, Sbackward_char
, 0, 1, "p",
76 "Move point left ARG characters (right if ARG negative).\n\
77 On attempt to pass beginning or end of buffer, stop and signal error.")
86 XSETINT (n
, - XINT (n
));
87 return Fforward_char (n
);
90 DEFUN ("forward-line", Fforward_line
, Sforward_line
, 0, 1, "p",
91 "Move ARG lines forward (backward if ARG is negative).\n\
92 Precisely, if point is on line I, move to the start of line I + ARG.\n\
93 If there isn't room, go as far as possible (no error).\n\
94 Returns the count of lines left to move. If moving forward,\n\
95 that is ARG - number of lines moved; if backward, ARG + number moved.\n\
96 With positive ARG, a non-empty line at the end counts as one line\n\
97 successfully moved (for the return value).")
103 int count
, shortage
, negp
;
114 pos
= scan_buffer ('\n', pos2
, 0, count
- negp
, &shortage
, 1);
119 && FETCH_CHAR (pos
- 1) != '\n')))
122 return make_number (negp
? - shortage
: shortage
);
125 DEFUN ("beginning-of-line", Fbeginning_of_line
, Sbeginning_of_line
,
127 "Move point to beginning of current line.\n\
128 With argument ARG not nil or 1, move forward ARG - 1 lines first.\n\
129 If scan reaches end of buffer, stop there without error.")
138 Fforward_line (make_number (XINT (n
) - 1));
142 DEFUN ("end-of-line", Fend_of_line
, Send_of_line
,
144 "Move point to end of current line.\n\
145 With argument ARG not nil or 1, move forward ARG - 1 lines first.\n\
146 If scan reaches end of buffer, stop there without error.")
158 SET_PT (find_before_next_newline (PT
, 0, XINT (n
) - (XINT (n
) <= 0)));
163 DEFUN ("delete-char", Fdelete_char
, Sdelete_char
, 1, 2, "p\nP",
164 "Delete the following ARG characters (previous, with negative arg).\n\
165 Optional second arg KILLFLAG non-nil means kill instead (save in kill ring).\n\
166 Interactively, ARG is the prefix arg, and KILLFLAG is set if\n\
167 ARG was explicitly specified.")
169 Lisp_Object n
, killflag
;
177 if (point
+ XINT (n
) < BEGV
)
178 Fsignal (Qbeginning_of_buffer
, Qnil
);
180 del_range (point
+ XINT (n
), point
);
184 if (point
+ XINT (n
) > ZV
)
185 Fsignal (Qend_of_buffer
, Qnil
);
187 del_range (point
, point
+ XINT (n
));
192 call1 (Qkill_forward_chars
, n
);
197 DEFUN ("delete-backward-char", Fdelete_backward_char
, Sdelete_backward_char
,
199 "Delete the previous ARG characters (following, with negative ARG).\n\
200 Optional second arg KILLFLAG non-nil means kill instead (save in kill ring).\n\
201 Interactively, ARG is the prefix arg, and KILLFLAG is set if\n\
202 ARG was explicitly specified.")
204 Lisp_Object n
, killflag
;
207 return Fdelete_char (make_number (-XINT (n
)), killflag
);
210 DEFUN ("self-insert-command", Fself_insert_command
, Sself_insert_command
, 1, 1, "p",
211 "Insert the character you type.\n\
212 Whichever character you type to run this command is inserted.")
216 CHECK_NUMBER (arg
, 0);
218 /* Barf if the key that invoked this was not a character. */
219 if (!INTEGERP (last_command_char
))
222 while (XINT (arg
) > 0)
224 /* Ok since old and new vals both nonneg */
225 XSETFASTINT (arg
, XFASTINT (arg
) - 1);
226 internal_self_insert (XINT (last_command_char
), XFASTINT (arg
) != 0);
232 DEFUN ("newline", Fnewline
, Snewline
, 0, 1, "P",
233 "Insert a newline. With arg, insert that many newlines.\n\
234 In Auto Fill mode, if no numeric arg, break the preceding line if it's long.")
242 arg
= Fprefix_numeric_value (arg1
);
244 if (!NILP (current_buffer
->read_only
))
245 Fbarf_if_buffer_read_only ();
247 /* Inserting a newline at the end of a line produces better
248 redisplay in try_window_id than inserting at the beginning of a
249 line, and the textual result is the same. So, if we're at
250 beginning of line, pretend to be at the end of the previous line.
252 We can't use internal_self_insert in that case since it won't do
253 the insertion correctly. Luckily, internal_self_insert's special
254 features all do nothing in that case. */
256 flag
= point
> BEGV
&& FETCH_CHAR (point
- 1) == '\n';
257 /* Don't do this if at the beginning of the window. */
258 if (XBUFFER (XWINDOW (selected_window
)->buffer
) == current_buffer
259 && marker_position (XWINDOW (selected_window
)->start
) == PT
)
262 #ifdef USE_TEXT_PROPERTIES
263 /* We cannot use this optimization if properties change
265 ??? We need to check for change hook properties, etc. */
267 if (! (point
- 1 > BEGV
&& ! property_change_between_p (point
- 2, point
)))
274 for (i
= XINT (arg
); i
> 0; i
--)
277 insert_and_inherit (&c1
, 1);
279 internal_self_insert ('\n', !NILP (arg1
));
282 #ifdef USE_TEXT_PROPERTIES
283 if (Vuse_hard_newlines
)
285 Lisp_Object from
, to
, sticky
;
286 XSETFASTINT (from
, PT
- arg
);
287 XSETFASTINT (to
, PT
);
288 Fput_text_property (from
, to
, Qhard
, Qt
, Qnil
);
289 /* If rear_nonsticky is not "t", locally add Qhard to the list. */
290 sticky
= Fget_text_property (from
, Qrear_nonsticky
, Qnil
);
292 || (CONSP (sticky
) && NILP (Fmemq (Qhard
, sticky
))))
294 sticky
= Fcons (Qhard
, sticky
);
295 Fput_text_property (from
, to
, Qrear_nonsticky
, sticky
, Qnil
);
307 /* Insert character C1. If NOAUTOFILL is nonzero, don't do autofill
308 even if it is enabled.
310 If this insertion is suitable for direct output (completely simple),
311 return 0. A value of 1 indicates this *might* not have been simple.
312 A value of 2 means this did things that call for an undo boundary. */
314 internal_self_insert (c1
, noautofill
)
318 extern Lisp_Object
Fexpand_abbrev ();
321 register enum syntaxcode synt
;
323 Lisp_Object overwrite
;
325 overwrite
= current_buffer
->overwrite_mode
;
326 if (!NILP (Vbefore_change_function
) || !NILP (Vafter_change_function
)
327 || !NILP (Vbefore_change_functions
) || !NILP (Vafter_change_functions
))
330 if (!NILP (overwrite
)
332 && (EQ (overwrite
, Qoverwrite_mode_binary
)
333 || (c
!= '\n' && FETCH_CHAR (point
) != '\n'))
334 && (EQ (overwrite
, Qoverwrite_mode_binary
)
335 || FETCH_CHAR (point
) != '\t'
336 || XINT (current_buffer
->tab_width
) <= 0
337 || XFASTINT (current_buffer
->tab_width
) > 20
338 || !((current_column () + 1) % XFASTINT (current_buffer
->tab_width
))))
340 del_range (point
, point
+ 1);
343 if (!NILP (current_buffer
->abbrev_mode
)
344 && SYNTAX (c
) != Sword
345 && NILP (current_buffer
->read_only
)
346 && point
> BEGV
&& SYNTAX (FETCH_CHAR (point
- 1)) == Sword
)
350 /* We can't trust the value of Fexpand_abbrev,
351 but if Fexpand_abbrev changed the buffer,
352 assume it expanded something. */
353 if (MODIFF
!= modiff
)
356 if ((c
== ' ' || c
== '\n')
358 && !NILP (current_buffer
->auto_fill_function
))
361 insert_and_inherit (&c1
, 1);
362 call0 (current_buffer
->auto_fill_function
);
364 insert_and_inherit (&c1
, 1);
368 insert_and_inherit (&c1
, 1);
370 if ((synt
== Sclose
|| synt
== Smath
)
371 && !NILP (Vblink_paren_function
) && INTERACTIVE
)
373 call0 (Vblink_paren_function
);
379 /* module initialization */
383 Qkill_backward_chars
= intern ("kill-backward-chars");
384 staticpro (&Qkill_backward_chars
);
386 Qkill_forward_chars
= intern ("kill-forward-chars");
387 staticpro (&Qkill_forward_chars
);
389 Qoverwrite_mode_binary
= intern ("overwrite-mode-binary");
390 staticpro (&Qoverwrite_mode_binary
);
392 Qhard
= intern ("hard");
395 DEFVAR_BOOL ("use-hard-newlines", &Vuse_hard_newlines
,
396 "Non-nil means to distinguish hard and soft newlines.
397 When this is non-nil, the functions `newline' and `open-line' add the
398 text-property `hard' to newlines that they insert. Also, a line is
399 only considered as a candidate to match `paragraph-start' or
400 `paragraph-separate' if it follows a hard newline. Newlines not
401 marked hard are called \"soft\", and are always internal to
402 paragraphs. The fill functions always insert soft newlines.");
403 Vuse_hard_newlines
= 0;
405 DEFVAR_LISP ("blink-paren-function", &Vblink_paren_function
,
406 "Function called, if non-nil, whenever a close parenthesis is inserted.\n\
407 More precisely, a char with closeparen syntax is self-inserted.");
408 Vblink_paren_function
= Qnil
;
410 defsubr (&Sforward_char
);
411 defsubr (&Sbackward_char
);
412 defsubr (&Sforward_line
);
413 defsubr (&Sbeginning_of_line
);
414 defsubr (&Send_of_line
);
416 defsubr (&Sdelete_char
);
417 defsubr (&Sdelete_backward_char
);
419 defsubr (&Sself_insert_command
);
427 initial_define_key (global_map
, Ctl ('M'), "newline");
428 initial_define_key (global_map
, Ctl ('I'), "self-insert-command");
429 for (n
= 040; n
< 0177; n
++)
430 initial_define_key (global_map
, n
, "self-insert-command");
432 for (n
= 0200; n
< 0240; n
++)
433 initial_define_key (global_map
, n
, "self-insert-command");
435 for (n
= 0240; n
< 0400; n
++)
436 initial_define_key (global_map
, n
, "self-insert-command");
438 initial_define_key (global_map
, Ctl ('A'), "beginning-of-line");
439 initial_define_key (global_map
, Ctl ('B'), "backward-char");
440 initial_define_key (global_map
, Ctl ('D'), "delete-char");
441 initial_define_key (global_map
, Ctl ('E'), "end-of-line");
442 initial_define_key (global_map
, Ctl ('F'), "forward-char");
443 initial_define_key (global_map
, 0177, "delete-backward-char");