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