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
;
30 /* A possible value for a buffer's overwrite-mode variable. */
31 Lisp_Object Qoverwrite_mode_binary
;
34 DEFUN ("forward-char", Fforward_char
, Sforward_char
, 0, 1, "p",
35 "Move point right ARG characters (left if ARG negative).\n\
36 On reaching end of buffer, stop and signal error.")
45 /* This used to just set point to point + XINT (n), and then check
46 to see if it was within boundaries. But now that SET_PT can
47 potentially do a lot of stuff (calling entering and exiting
48 hooks, etcetera), that's not a good approach. So we validate the
49 proposed position, then set point. */
51 int new_point
= point
+ XINT (n
);
56 Fsignal (Qbeginning_of_buffer
, Qnil
);
61 Fsignal (Qend_of_buffer
, Qnil
);
70 DEFUN ("backward-char", Fbackward_char
, Sbackward_char
, 0, 1, "p",
71 "Move point left ARG characters (right if ARG negative).\n\
72 On attempt to pass beginning or end of buffer, stop and signal error.")
81 XSETINT (n
, - XINT (n
));
82 return Fforward_char (n
);
85 DEFUN ("forward-line", Fforward_line
, Sforward_line
, 0, 1, "p",
86 "Move ARG lines forward (backward if ARG is negative).\n\
87 Precisely, if point is on line I, move to the start of line I + ARG.\n\
88 If there isn't room, go as far as possible (no error).\n\
89 Returns the count of lines left to move. If moving forward,\n\
90 that is ARG - number of lines moved; if backward, ARG + number moved.\n\
91 With positive ARG, a non-empty line at the end counts as one line\n\
92 successfully moved (for the return value).")
98 int count
, shortage
, negp
;
109 pos
= scan_buffer ('\n', pos2
, 0, count
- negp
, &shortage
, 1);
114 && FETCH_CHAR (pos
- 1) != '\n')))
117 return make_number (negp
? - shortage
: shortage
);
120 DEFUN ("beginning-of-line", Fbeginning_of_line
, Sbeginning_of_line
,
122 "Move point to beginning of current line.\n\
123 With argument ARG not nil or 1, move forward ARG - 1 lines first.\n\
124 If scan reaches end of buffer, stop there without error.")
133 Fforward_line (make_number (XINT (n
) - 1));
137 DEFUN ("end-of-line", Fend_of_line
, Send_of_line
,
139 "Move point to end of current line.\n\
140 With argument ARG not nil or 1, move forward ARG - 1 lines first.\n\
141 If scan reaches end of buffer, stop there without error.")
153 SET_PT (find_before_next_newline (PT
, 0, XINT (n
) - (XINT (n
) <= 0)));
158 DEFUN ("delete-char", Fdelete_char
, Sdelete_char
, 1, 2, "p\nP",
159 "Delete the following ARG characters (previous, with negative arg).\n\
160 Optional second arg KILLFLAG non-nil means kill instead (save in kill ring).\n\
161 Interactively, ARG is the prefix arg, and KILLFLAG is set if\n\
162 ARG was explicitly specified.")
164 Lisp_Object n
, killflag
;
172 if (point
+ XINT (n
) < BEGV
)
173 Fsignal (Qbeginning_of_buffer
, Qnil
);
175 del_range (point
+ XINT (n
), point
);
179 if (point
+ XINT (n
) > ZV
)
180 Fsignal (Qend_of_buffer
, Qnil
);
182 del_range (point
, point
+ XINT (n
));
187 call1 (Qkill_forward_chars
, n
);
192 DEFUN ("delete-backward-char", Fdelete_backward_char
, Sdelete_backward_char
,
194 "Delete the previous ARG characters (following, with negative ARG).\n\
195 Optional second arg KILLFLAG non-nil means kill instead (save in kill ring).\n\
196 Interactively, ARG is the prefix arg, and KILLFLAG is set if\n\
197 ARG was explicitly specified.")
199 Lisp_Object n
, killflag
;
202 return Fdelete_char (make_number (-XINT (n
)), killflag
);
205 DEFUN ("self-insert-command", Fself_insert_command
, Sself_insert_command
, 1, 1, "p",
206 "Insert the character you type.\n\
207 Whichever character you type to run this command is inserted.")
211 CHECK_NUMBER (arg
, 0);
213 /* Barf if the key that invoked this was not a character. */
214 if (!INTEGERP (last_command_char
))
217 while (XINT (arg
) > 0)
219 /* Ok since old and new vals both nonneg */
220 XSETFASTINT (arg
, XFASTINT (arg
) - 1);
221 internal_self_insert (XINT (last_command_char
), XFASTINT (arg
) != 0);
227 DEFUN ("newline", Fnewline
, Snewline
, 0, 1, "P",
228 "Insert a newline. With arg, insert that many newlines.\n\
229 In Auto Fill mode, if no numeric arg, break the preceding line if it's long.")
237 arg
= Fprefix_numeric_value (arg1
);
239 if (!NILP (current_buffer
->read_only
))
240 Fbarf_if_buffer_read_only ();
242 /* Inserting a newline at the end of a line produces better
243 redisplay in try_window_id than inserting at the beginning of a
244 line, and the textual result is the same. So, if we're at
245 beginning of line, pretend to be at the end of the previous line.
247 We can't use internal_self_insert in that case since it won't do
248 the insertion correctly. Luckily, internal_self_insert's special
249 features all do nothing in that case. */
251 flag
= point
> BEGV
&& FETCH_CHAR (point
- 1) == '\n';
252 /* Don't do this if at the beginning of the window. */
253 if (XBUFFER (XWINDOW (selected_window
)->buffer
) == current_buffer
254 && marker_position (XWINDOW (selected_window
)->start
) == PT
)
257 #ifdef USE_TEXT_PROPERTIES
258 /* We cannot use this optimization if properties change
260 ??? We need to check for change hook properties, etc. */
262 if (! (point
- 1 > BEGV
&& ! property_change_between_p (point
- 2, point
)))
269 while (XINT (arg
) > 0)
272 insert_and_inherit (&c1
, 1);
274 internal_self_insert ('\n', !NILP (arg1
));
275 /* Ok since old and new vals both nonneg */
276 XSETFASTINT (arg
, XFASTINT (arg
) - 1);
285 /* Insert character C1. If NOAUTOFILL is nonzero, don't do autofill
286 even if it is enabled.
288 If this insertion is suitable for direct output (completely simple),
289 return 0. A value of 1 indicates this *might* not have been simple.
290 A value of 2 means this did things that call for an undo boundary. */
292 internal_self_insert (c1
, noautofill
)
296 extern Lisp_Object
Fexpand_abbrev ();
299 register enum syntaxcode synt
;
301 Lisp_Object overwrite
;
303 overwrite
= current_buffer
->overwrite_mode
;
304 if (!NILP (Vbefore_change_function
) || !NILP (Vafter_change_function
)
305 || !NILP (Vbefore_change_functions
) || !NILP (Vafter_change_functions
))
308 if (!NILP (overwrite
)
310 && (EQ (overwrite
, Qoverwrite_mode_binary
)
311 || (c
!= '\n' && FETCH_CHAR (point
) != '\n'))
312 && (EQ (overwrite
, Qoverwrite_mode_binary
)
313 || FETCH_CHAR (point
) != '\t'
314 || XINT (current_buffer
->tab_width
) <= 0
315 || XFASTINT (current_buffer
->tab_width
) > 20
316 || !((current_column () + 1) % XFASTINT (current_buffer
->tab_width
))))
318 del_range (point
, point
+ 1);
321 if (!NILP (current_buffer
->abbrev_mode
)
322 && SYNTAX (c
) != Sword
323 && NILP (current_buffer
->read_only
)
324 && point
> BEGV
&& SYNTAX (FETCH_CHAR (point
- 1)) == Sword
)
328 /* We can't trust the value of Fexpand_abbrev,
329 but if Fexpand_abbrev changed the buffer,
330 assume it expanded something. */
331 if (MODIFF
!= modiff
)
334 if ((c
== ' ' || c
== '\n')
336 && !NILP (current_buffer
->auto_fill_function
)
337 && current_column () > XFASTINT (current_buffer
->fill_column
))
340 insert_and_inherit (&c1
, 1);
341 call0 (current_buffer
->auto_fill_function
);
343 insert_and_inherit (&c1
, 1);
347 insert_and_inherit (&c1
, 1);
349 if ((synt
== Sclose
|| synt
== Smath
)
350 && !NILP (Vblink_paren_function
) && INTERACTIVE
)
352 call0 (Vblink_paren_function
);
358 /* module initialization */
362 Qkill_backward_chars
= intern ("kill-backward-chars");
363 staticpro (&Qkill_backward_chars
);
365 Qkill_forward_chars
= intern ("kill-forward-chars");
366 staticpro (&Qkill_forward_chars
);
368 Qoverwrite_mode_binary
= intern ("overwrite-mode-binary");
369 staticpro (&Qoverwrite_mode_binary
);
371 DEFVAR_LISP ("blink-paren-function", &Vblink_paren_function
,
372 "Function called, if non-nil, whenever a close parenthesis is inserted.\n\
373 More precisely, a char with closeparen syntax is self-inserted.");
374 Vblink_paren_function
= Qnil
;
376 defsubr (&Sforward_char
);
377 defsubr (&Sbackward_char
);
378 defsubr (&Sforward_line
);
379 defsubr (&Sbeginning_of_line
);
380 defsubr (&Send_of_line
);
382 defsubr (&Sdelete_char
);
383 defsubr (&Sdelete_backward_char
);
385 defsubr (&Sself_insert_command
);
393 initial_define_key (global_map
, Ctl('M'), "newline");
394 initial_define_key (global_map
, Ctl('I'), "self-insert-command");
395 for (n
= 040; n
< 0177; n
++)
396 initial_define_key (global_map
, n
, "self-insert-command");
398 for (n
= 0200; n
< 0240; n
++)
399 initial_define_key (global_map
, n
, "self-insert-command");
401 for (n
= 0240; n
< 0400; n
++)
402 initial_define_key (global_map
, n
, "self-insert-command");
404 initial_define_key (global_map
, Ctl ('A'), "beginning-of-line");
405 initial_define_key (global_map
, Ctl ('B'), "backward-char");
406 initial_define_key (global_map
, Ctl ('D'), "delete-char");
407 initial_define_key (global_map
, Ctl ('E'), "end-of-line");
408 initial_define_key (global_map
, Ctl ('F'), "forward-char");
409 initial_define_key (global_map
, 0177, "delete-backward-char");