Update FSF's address in the preamble.
[bpt/emacs.git] / src / cmds.c
CommitLineData
cd645247 1/* Simple built-in editing commands.
f8c25f1b 2 Copyright (C) 1985, 1993, 1994, 1995 Free Software Foundation, Inc.
cd645247
JB
3
4This file is part of GNU Emacs.
5
6GNU Emacs is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
502ddf23 8the Free Software Foundation; either version 2, or (at your option)
cd645247
JB
9any later version.
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Emacs; see the file COPYING. If not, write to
3b7ad313
EN
18the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA. */
cd645247
JB
20
21
18160b98 22#include <config.h>
cd645247
JB
23#include "lisp.h"
24#include "commands.h"
25#include "buffer.h"
26#include "syntax.h"
f109dfa2 27#include "window.h"
346e0c2d 28#include "keyboard.h"
cd645247
JB
29
30Lisp_Object Qkill_forward_chars, Qkill_backward_chars, Vblink_paren_function;
31
6bbb0d4a
JB
32/* A possible value for a buffer's overwrite-mode variable. */
33Lisp_Object Qoverwrite_mode_binary;
34
189fad68
RS
35/* Non-nil means put this face on the next self-inserting character. */
36Lisp_Object Vself_insert_face;
37
38/* This is the command that set up Vself_insert_face. */
39Lisp_Object Vself_insert_face_command;
40
189fad68 41extern Lisp_Object Qface;
cd645247
JB
42\f
43DEFUN ("forward-char", Fforward_char, Sforward_char, 0, 1, "p",
72d5f589 44 "Move point right N characters (left if N is negative).\n\
cd645247 45On reaching end of buffer, stop and signal error.")
72d5f589
EN
46 (n)
47 Lisp_Object n;
cd645247 48{
72d5f589
EN
49 if (NILP (n))
50 XSETFASTINT (n, 1);
cd645247 51 else
72d5f589 52 CHECK_NUMBER (n, 0);
cd645247 53
72d5f589 54 /* This used to just set point to point + XINT (n), and then check
7b502dc3
JB
55 to see if it was within boundaries. But now that SET_PT can
56 potentially do a lot of stuff (calling entering and exiting
57 hooks, etcetera), that's not a good approach. So we validate the
58 proposed position, then set point. */
59 {
72d5f589 60 int new_point = point + XINT (n);
7b502dc3
JB
61
62 if (new_point < BEGV)
63 {
64 SET_PT (BEGV);
65 Fsignal (Qbeginning_of_buffer, Qnil);
66 }
67 if (new_point > ZV)
68 {
69 SET_PT (ZV);
70 Fsignal (Qend_of_buffer, Qnil);
71 }
72
73 SET_PT (new_point);
74 }
75
cd645247
JB
76 return Qnil;
77}
78
79DEFUN ("backward-char", Fbackward_char, Sbackward_char, 0, 1, "p",
72d5f589 80 "Move point left N characters (right if N is negative).\n\
cd645247 81On attempt to pass beginning or end of buffer, stop and signal error.")
72d5f589
EN
82 (n)
83 Lisp_Object n;
cd645247 84{
72d5f589
EN
85 if (NILP (n))
86 XSETFASTINT (n, 1);
cd645247 87 else
72d5f589 88 CHECK_NUMBER (n, 0);
cd645247 89
72d5f589
EN
90 XSETINT (n, - XINT (n));
91 return Fforward_char (n);
cd645247
JB
92}
93
94DEFUN ("forward-line", Fforward_line, Sforward_line, 0, 1, "p",
72d5f589
EN
95 "Move N lines forward (backward if N is negative).\n\
96Precisely, if point is on line I, move to the start of line I + N.\n\
cd645247
JB
97If there isn't room, go as far as possible (no error).\n\
98Returns the count of lines left to move. If moving forward,\n\
72d5f589
EN
99that is N - number of lines moved; if backward, N + number moved.\n\
100With positive N, a non-empty line at the end counts as one line\n\
cd645247
JB
101 successfully moved (for the return value).")
102 (n)
103 Lisp_Object n;
104{
105 int pos2 = point;
106 int pos;
107 int count, shortage, negp;
108
265a9e55 109 if (NILP (n))
cd645247
JB
110 count = 1;
111 else
112 {
113 CHECK_NUMBER (n, 0);
114 count = XINT (n);
115 }
116
117 negp = count <= 0;
4f5d0c3c 118 pos = scan_buffer ('\n', pos2, 0, count - negp, &shortage, 1);
cd645247
JB
119 if (shortage > 0
120 && (negp
502ddf23
JB
121 || (ZV > BEGV
122 && pos != pos2
cd645247
JB
123 && FETCH_CHAR (pos - 1) != '\n')))
124 shortage--;
125 SET_PT (pos);
126 return make_number (negp ? - shortage : shortage);
127}
128
129DEFUN ("beginning-of-line", Fbeginning_of_line, Sbeginning_of_line,
130 0, 1, "p",
131 "Move point to beginning of current line.\n\
72d5f589 132With argument N not nil or 1, move forward N - 1 lines first.\n\
cd645247
JB
133If scan reaches end of buffer, stop there without error.")
134 (n)
135 Lisp_Object n;
136{
265a9e55 137 if (NILP (n))
48c7cef2 138 XSETFASTINT (n, 1);
cd645247
JB
139 else
140 CHECK_NUMBER (n, 0);
141
142 Fforward_line (make_number (XINT (n) - 1));
143 return Qnil;
144}
145
146DEFUN ("end-of-line", Fend_of_line, Send_of_line,
147 0, 1, "p",
148 "Move point to end of current line.\n\
72d5f589 149With argument N not nil or 1, move forward N - 1 lines first.\n\
cd645247
JB
150If scan reaches end of buffer, stop there without error.")
151 (n)
152 Lisp_Object n;
153{
154 register int pos;
155 register int stop;
156
265a9e55 157 if (NILP (n))
48c7cef2 158 XSETFASTINT (n, 1);
cd645247
JB
159 else
160 CHECK_NUMBER (n, 0);
161
4f5d0c3c 162 SET_PT (find_before_next_newline (PT, 0, XINT (n) - (XINT (n) <= 0)));
cd645247
JB
163
164 return Qnil;
165}
166
167DEFUN ("delete-char", Fdelete_char, Sdelete_char, 1, 2, "p\nP",
72d5f589 168 "Delete the following N characters (previous if N is negative).\n\
cd645247 169Optional second arg KILLFLAG non-nil means kill instead (save in kill ring).\n\
72d5f589
EN
170Interactively, N is the prefix arg, and KILLFLAG is set if\n\
171N was explicitly specified.")
cd645247
JB
172 (n, killflag)
173 Lisp_Object n, killflag;
174{
175 CHECK_NUMBER (n, 0);
176
265a9e55 177 if (NILP (killflag))
cd645247
JB
178 {
179 if (XINT (n) < 0)
180 {
181 if (point + XINT (n) < BEGV)
182 Fsignal (Qbeginning_of_buffer, Qnil);
183 else
184 del_range (point + XINT (n), point);
185 }
186 else
187 {
188 if (point + XINT (n) > ZV)
189 Fsignal (Qend_of_buffer, Qnil);
190 else
191 del_range (point, point + XINT (n));
192 }
193 }
194 else
195 {
196 call1 (Qkill_forward_chars, n);
197 }
198 return Qnil;
199}
200
201DEFUN ("delete-backward-char", Fdelete_backward_char, Sdelete_backward_char,
202 1, 2, "p\nP",
72d5f589 203 "Delete the previous N characters (following if N is negative).\n\
cd645247 204Optional second arg KILLFLAG non-nil means kill instead (save in kill ring).\n\
72d5f589
EN
205Interactively, N is the prefix arg, and KILLFLAG is set if\n\
206N was explicitly specified.")
cd645247
JB
207 (n, killflag)
208 Lisp_Object n, killflag;
209{
210 CHECK_NUMBER (n, 0);
211 return Fdelete_char (make_number (-XINT (n)), killflag);
212}
213
214DEFUN ("self-insert-command", Fself_insert_command, Sself_insert_command, 1, 1, "p",
215 "Insert the character you type.\n\
216Whichever character you type to run this command is inserted.")
72d5f589
EN
217 (n)
218 Lisp_Object n;
cd645247 219{
72d5f589 220 CHECK_NUMBER (n, 0);
cd645247
JB
221
222 /* Barf if the key that invoked this was not a character. */
ed76f667 223 if (!INTEGERP (last_command_char))
cd645247 224 bitch_at_user ();
72d5f589 225 else if (XINT (n) >= 2 && NILP (current_buffer->overwrite_mode))
2718dfa4 226 {
72d5f589 227 XSETFASTINT (n, XFASTINT (n) - 2);
2718dfa4
RS
228 /* The first one might want to expand an abbrev. */
229 internal_self_insert (XINT (last_command_char), 1);
230 /* The bulk of the copies of this char can be inserted simply.
231 We don't have to handle a user-specified face specially
232 because it will get inherited from the first char inserted. */
72d5f589 233 Finsert_char (last_command_char, n, Qt);
2718dfa4
RS
234 /* The last one might want to auto-fill. */
235 internal_self_insert (XINT (last_command_char), 0);
236 }
cd645247 237 else
72d5f589 238 while (XINT (n) > 0)
cd645247 239 {
f58dd69b 240 /* Ok since old and new vals both nonneg */
72d5f589
EN
241 XSETFASTINT (n, XFASTINT (n) - 1);
242 internal_self_insert (XINT (last_command_char), XFASTINT (n) != 0);
cd645247
JB
243 }
244
245 return Qnil;
246}
247
4c6e656f
RS
248/* Insert character C1. If NOAUTOFILL is nonzero, don't do autofill
249 even if it is enabled.
250
251 If this insertion is suitable for direct output (completely simple),
aa52fef9
RS
252 return 0. A value of 1 indicates this *might* not have been simple.
253 A value of 2 means this did things that call for an undo boundary. */
4c6e656f 254
cd645247 255internal_self_insert (c1, noautofill)
af39ac8c
RS
256 /* This has to be unsigned char; when it is char,
257 some compilers sign-extend it in SYNTAX_ENTRY, despite
258 the casts to unsigned char there. */
259 unsigned char c1;
cd645247
JB
260 int noautofill;
261{
262 extern Lisp_Object Fexpand_abbrev ();
263 int hairy = 0;
264 Lisp_Object tem;
265 register enum syntaxcode synt;
266 register int c = c1;
e7aacab7 267 Lisp_Object overwrite;
cd645247 268
e7aacab7 269 overwrite = current_buffer->overwrite_mode;
166a4263
RS
270 if (!NILP (Vbefore_change_function) || !NILP (Vafter_change_function)
271 || !NILP (Vbefore_change_functions) || !NILP (Vafter_change_functions))
cd645247
JB
272 hairy = 1;
273
6bbb0d4a 274 if (!NILP (overwrite)
cd645247 275 && point < ZV
6bbb0d4a
JB
276 && (EQ (overwrite, Qoverwrite_mode_binary)
277 || (c != '\n' && FETCH_CHAR (point) != '\n'))
278 && (EQ (overwrite, Qoverwrite_mode_binary)
e686c647 279 || FETCH_CHAR (point) != '\t'
cd645247 280 || XINT (current_buffer->tab_width) <= 0
2234dd63 281 || XFASTINT (current_buffer->tab_width) > 20
cd645247
JB
282 || !((current_column () + 1) % XFASTINT (current_buffer->tab_width))))
283 {
284 del_range (point, point + 1);
aa52fef9 285 hairy = 2;
cd645247 286 }
265a9e55 287 if (!NILP (current_buffer->abbrev_mode)
cd645247 288 && SYNTAX (c) != Sword
265a9e55 289 && NILP (current_buffer->read_only)
cd645247
JB
290 && point > BEGV && SYNTAX (FETCH_CHAR (point - 1)) == Sword)
291 {
ee8caabb 292 int modiff = MODIFF;
4c6e656f
RS
293 Fexpand_abbrev ();
294 /* We can't trust the value of Fexpand_abbrev,
ee8caabb
RS
295 but if Fexpand_abbrev changed the buffer,
296 assume it expanded something. */
297 if (MODIFF != modiff)
aa52fef9 298 hairy = 2;
cd645247
JB
299 }
300 if ((c == ' ' || c == '\n')
301 && !noautofill
3de15b7a 302 && !NILP (current_buffer->auto_fill_function))
cd645247 303 {
2e16553c
BG
304 insert_and_inherit (&c1, 1);
305 if (c1 == '\n')
306 /* After inserting a newline, move to previous line and fill */
307 /* that. Must have the newline in place already so filling and */
308 /* justification, if any, know where the end is going to be. */
309 SET_PT (point - 1);
cd645247
JB
310 call0 (current_buffer->auto_fill_function);
311 if (c1 == '\n')
2e16553c 312 SET_PT (point + 1);
aa52fef9 313 hairy = 2;
cd645247
JB
314 }
315 else
b9a7407f 316 insert_and_inherit (&c1, 1);
189fad68 317
38d404db 318#ifdef HAVE_FACES
189fad68
RS
319 /* If previous command specified a face to use, use it. */
320 if (!NILP (Vself_insert_face)
346e0c2d 321 && EQ (current_kboard->Vlast_command, Vself_insert_face_command))
189fad68
RS
322 {
323 Lisp_Object before, after;
324 XSETINT (before, PT - 1);
325 XSETINT (after, PT);
326 Fput_text_property (before, after, Qface, Vself_insert_face, Qnil);
327 Vself_insert_face = Qnil;
328 }
38d404db 329#endif
cd645247
JB
330 synt = SYNTAX (c);
331 if ((synt == Sclose || synt == Smath)
2718dfa4
RS
332 && !NILP (Vblink_paren_function) && INTERACTIVE
333 && !noautofill)
cd645247
JB
334 {
335 call0 (Vblink_paren_function);
aa52fef9 336 hairy = 2;
cd645247
JB
337 }
338 return hairy;
339}
340\f
341/* module initialization */
342
343syms_of_cmds ()
344{
345 Qkill_backward_chars = intern ("kill-backward-chars");
346 staticpro (&Qkill_backward_chars);
347
348 Qkill_forward_chars = intern ("kill-forward-chars");
349 staticpro (&Qkill_forward_chars);
350
6bbb0d4a
JB
351 Qoverwrite_mode_binary = intern ("overwrite-mode-binary");
352 staticpro (&Qoverwrite_mode_binary);
e686c647 353
189fad68
RS
354 DEFVAR_LISP ("self-insert-face", &Vself_insert_face,
355 "If non-nil, set the face of the next self-inserting character to this.\n\
356See also `self-insert-face-command'.");
357 Vself_insert_face = Qnil;
358
359 DEFVAR_LISP ("self-insert-face-command", &Vself_insert_face_command,
360 "This is the command that set up `self-insert-face'.\n\
361If `last-command' does not equal this value, we ignore `self-insert-face'.");
362 Vself_insert_face_command = Qnil;
363
cd645247
JB
364 DEFVAR_LISP ("blink-paren-function", &Vblink_paren_function,
365 "Function called, if non-nil, whenever a close parenthesis is inserted.\n\
366More precisely, a char with closeparen syntax is self-inserted.");
367 Vblink_paren_function = Qnil;
368
369 defsubr (&Sforward_char);
370 defsubr (&Sbackward_char);
371 defsubr (&Sforward_line);
372 defsubr (&Sbeginning_of_line);
373 defsubr (&Send_of_line);
374
375 defsubr (&Sdelete_char);
376 defsubr (&Sdelete_backward_char);
377
378 defsubr (&Sself_insert_command);
cd645247
JB
379}
380
381keys_of_cmds ()
382{
383 int n;
384
cbf65115 385 initial_define_key (global_map, Ctl ('I'), "self-insert-command");
cd645247
JB
386 for (n = 040; n < 0177; n++)
387 initial_define_key (global_map, n, "self-insert-command");
cf9cdc11
RS
388#ifdef MSDOS
389 for (n = 0200; n < 0240; n++)
390 initial_define_key (global_map, n, "self-insert-command");
391#endif
94748cb9 392 for (n = 0240; n < 0400; n++)
eb46da6a 393 initial_define_key (global_map, n, "self-insert-command");
cd645247
JB
394
395 initial_define_key (global_map, Ctl ('A'), "beginning-of-line");
396 initial_define_key (global_map, Ctl ('B'), "backward-char");
397 initial_define_key (global_map, Ctl ('D'), "delete-char");
398 initial_define_key (global_map, Ctl ('E'), "end-of-line");
399 initial_define_key (global_map, Ctl ('F'), "forward-char");
400 initial_define_key (global_map, 0177, "delete-backward-char");
401}