(Ffile_name_completion, file_name_completion): Use type test macros.
[bpt/emacs.git] / src / cmds.c
CommitLineData
cd645247 1/* Simple built-in editing commands.
3a22ee35 2 Copyright (C) 1985, 1993, 1994 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"
cd645247
JB
27
28Lisp_Object Qkill_forward_chars, Qkill_backward_chars, Vblink_paren_function;
29
6bbb0d4a
JB
30/* A possible value for a buffer's overwrite-mode variable. */
31Lisp_Object Qoverwrite_mode_binary;
32
cd645247
JB
33\f
34DEFUN ("forward-char", Fforward_char, Sforward_char, 0, 1, "p",
35 "Move point right ARG characters (left if ARG negative).\n\
36On reaching end of buffer, stop and signal error.")
37 (n)
38 Lisp_Object n;
39{
265a9e55 40 if (NILP (n))
cd645247
JB
41 XFASTINT (n) = 1;
42 else
43 CHECK_NUMBER (n, 0);
44
7b502dc3
JB
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. */
50 {
51 int new_point = point + XINT (n);
52
53 if (new_point < BEGV)
54 {
55 SET_PT (BEGV);
56 Fsignal (Qbeginning_of_buffer, Qnil);
57 }
58 if (new_point > ZV)
59 {
60 SET_PT (ZV);
61 Fsignal (Qend_of_buffer, Qnil);
62 }
63
64 SET_PT (new_point);
65 }
66
cd645247
JB
67 return Qnil;
68}
69
70DEFUN ("backward-char", Fbackward_char, Sbackward_char, 0, 1, "p",
71 "Move point left ARG characters (right if ARG negative).\n\
72On attempt to pass beginning or end of buffer, stop and signal error.")
73 (n)
74 Lisp_Object n;
75{
265a9e55 76 if (NILP (n))
cd645247
JB
77 XFASTINT (n) = 1;
78 else
79 CHECK_NUMBER (n, 0);
80
81 XSETINT (n, - XINT (n));
82 return Fforward_char (n);
83}
84
85DEFUN ("forward-line", Fforward_line, Sforward_line, 0, 1, "p",
86 "Move ARG lines forward (backward if ARG is negative).\n\
87Precisely, if point is on line I, move to the start of line I + ARG.\n\
88If there isn't room, go as far as possible (no error).\n\
89Returns the count of lines left to move. If moving forward,\n\
90that is ARG - number of lines moved; if backward, ARG + number moved.\n\
91With positive ARG, a non-empty line at the end counts as one line\n\
92 successfully moved (for the return value).")
93 (n)
94 Lisp_Object n;
95{
96 int pos2 = point;
97 int pos;
98 int count, shortage, negp;
99
265a9e55 100 if (NILP (n))
cd645247
JB
101 count = 1;
102 else
103 {
104 CHECK_NUMBER (n, 0);
105 count = XINT (n);
106 }
107
108 negp = count <= 0;
0132c70c 109 pos = scan_buffer ('\n', pos2, count - negp, &shortage, 1);
cd645247
JB
110 if (shortage > 0
111 && (negp
502ddf23
JB
112 || (ZV > BEGV
113 && pos != pos2
cd645247
JB
114 && FETCH_CHAR (pos - 1) != '\n')))
115 shortage--;
116 SET_PT (pos);
117 return make_number (negp ? - shortage : shortage);
118}
119
120DEFUN ("beginning-of-line", Fbeginning_of_line, Sbeginning_of_line,
121 0, 1, "p",
122 "Move point to beginning of current line.\n\
123With argument ARG not nil or 1, move forward ARG - 1 lines first.\n\
124If scan reaches end of buffer, stop there without error.")
125 (n)
126 Lisp_Object n;
127{
265a9e55 128 if (NILP (n))
cd645247
JB
129 XFASTINT (n) = 1;
130 else
131 CHECK_NUMBER (n, 0);
132
133 Fforward_line (make_number (XINT (n) - 1));
134 return Qnil;
135}
136
137DEFUN ("end-of-line", Fend_of_line, Send_of_line,
138 0, 1, "p",
139 "Move point to end of current line.\n\
140With argument ARG not nil or 1, move forward ARG - 1 lines first.\n\
141If scan reaches end of buffer, stop there without error.")
142 (n)
143 Lisp_Object n;
144{
145 register int pos;
146 register int stop;
147
265a9e55 148 if (NILP (n))
cd645247
JB
149 XFASTINT (n) = 1;
150 else
151 CHECK_NUMBER (n, 0);
152
153 if (XINT (n) != 1)
154 Fforward_line (make_number (XINT (n) - 1));
155
156 pos = point;
157 stop = ZV;
158 while (pos < stop && FETCH_CHAR (pos) != '\n') pos++;
159 SET_PT (pos);
160
161 return Qnil;
162}
163
164DEFUN ("delete-char", Fdelete_char, Sdelete_char, 1, 2, "p\nP",
165 "Delete the following ARG characters (previous, with negative arg).\n\
166Optional second arg KILLFLAG non-nil means kill instead (save in kill ring).\n\
167Interactively, ARG is the prefix arg, and KILLFLAG is set if\n\
168ARG was explicitly specified.")
169 (n, killflag)
170 Lisp_Object n, killflag;
171{
172 CHECK_NUMBER (n, 0);
173
265a9e55 174 if (NILP (killflag))
cd645247
JB
175 {
176 if (XINT (n) < 0)
177 {
178 if (point + XINT (n) < BEGV)
179 Fsignal (Qbeginning_of_buffer, Qnil);
180 else
181 del_range (point + XINT (n), point);
182 }
183 else
184 {
185 if (point + XINT (n) > ZV)
186 Fsignal (Qend_of_buffer, Qnil);
187 else
188 del_range (point, point + XINT (n));
189 }
190 }
191 else
192 {
193 call1 (Qkill_forward_chars, n);
194 }
195 return Qnil;
196}
197
198DEFUN ("delete-backward-char", Fdelete_backward_char, Sdelete_backward_char,
199 1, 2, "p\nP",
200 "Delete the previous ARG characters (following, with negative ARG).\n\
201Optional second arg KILLFLAG non-nil means kill instead (save in kill ring).\n\
202Interactively, ARG is the prefix arg, and KILLFLAG is set if\n\
203ARG was explicitly specified.")
204 (n, killflag)
205 Lisp_Object n, killflag;
206{
207 CHECK_NUMBER (n, 0);
208 return Fdelete_char (make_number (-XINT (n)), killflag);
209}
210
211DEFUN ("self-insert-command", Fself_insert_command, Sself_insert_command, 1, 1, "p",
212 "Insert the character you type.\n\
213Whichever character you type to run this command is inserted.")
214 (arg)
215 Lisp_Object arg;
216{
217 CHECK_NUMBER (arg, 0);
218
219 /* Barf if the key that invoked this was not a character. */
220 if (XTYPE (last_command_char) != Lisp_Int)
221 bitch_at_user ();
222 else
223 while (XINT (arg) > 0)
224 {
225 XFASTINT (arg)--; /* Ok since old and new vals both nonneg */
226 internal_self_insert (XINT (last_command_char), XFASTINT (arg) != 0);
227 }
228
229 return Qnil;
230}
231
232DEFUN ("newline", Fnewline, Snewline, 0, 1, "P",
233 "Insert a newline. With arg, insert that many newlines.\n\
234In Auto Fill mode, if no numeric arg, break the preceding line if it's long.")
235 (arg1)
236 Lisp_Object arg1;
237{
238 int flag;
239 Lisp_Object arg;
240 char c1 = '\n';
241
242 arg = Fprefix_numeric_value (arg1);
243
265a9e55 244 if (!NILP (current_buffer->read_only))
69f19f89 245 Fbarf_if_buffer_read_only ();
cd645247 246
c39e6cc2 247 /* Inserting a newline at the end of a line produces better
eb8c3be9 248 redisplay in try_window_id than inserting at the beginning of a
c39e6cc2
JB
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.
251
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. */
cd645247
JB
255
256 flag = point > BEGV && FETCH_CHAR (point - 1) == '\n';
f109dfa2
RS
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)
260 flag = 0;
261
7c011261 262#ifdef USE_TEXT_PROPERTIES
dbf8da39
RS
263 /* We cannot use this optimization if properties change
264 in the vicinity.
265 ??? We need to check for change hook properties, etc. */
266 if (flag)
267 if (! (point - 1 > BEGV && ! property_change_between_p (point - 2, point)))
268 flag = 0;
7c011261 269#endif
dbf8da39
RS
270
271 if (flag)
272 SET_PT (point - 1);
cd645247
JB
273
274 while (XINT (arg) > 0)
275 {
276 if (flag)
277 insert (&c1, 1);
278 else
265a9e55 279 internal_self_insert ('\n', !NILP (arg1));
cd645247
JB
280 XFASTINT (arg)--; /* Ok since old and new vals both nonneg */
281 }
282
283 if (flag)
284 SET_PT (point + 1);
285
286 return Qnil;
287}
288
4c6e656f
RS
289/* Insert character C1. If NOAUTOFILL is nonzero, don't do autofill
290 even if it is enabled.
291
292 If this insertion is suitable for direct output (completely simple),
aa52fef9
RS
293 return 0. A value of 1 indicates this *might* not have been simple.
294 A value of 2 means this did things that call for an undo boundary. */
4c6e656f 295
cd645247
JB
296internal_self_insert (c1, noautofill)
297 char c1;
298 int noautofill;
299{
300 extern Lisp_Object Fexpand_abbrev ();
301 int hairy = 0;
302 Lisp_Object tem;
303 register enum syntaxcode synt;
304 register int c = c1;
e7aacab7 305 Lisp_Object overwrite;
cd645247 306
e7aacab7 307 overwrite = current_buffer->overwrite_mode;
166a4263
RS
308 if (!NILP (Vbefore_change_function) || !NILP (Vafter_change_function)
309 || !NILP (Vbefore_change_functions) || !NILP (Vafter_change_functions))
cd645247
JB
310 hairy = 1;
311
6bbb0d4a 312 if (!NILP (overwrite)
cd645247 313 && point < ZV
6bbb0d4a
JB
314 && (EQ (overwrite, Qoverwrite_mode_binary)
315 || (c != '\n' && FETCH_CHAR (point) != '\n'))
316 && (EQ (overwrite, Qoverwrite_mode_binary)
e686c647 317 || FETCH_CHAR (point) != '\t'
cd645247 318 || XINT (current_buffer->tab_width) <= 0
2234dd63 319 || XFASTINT (current_buffer->tab_width) > 20
cd645247
JB
320 || !((current_column () + 1) % XFASTINT (current_buffer->tab_width))))
321 {
322 del_range (point, point + 1);
aa52fef9 323 hairy = 2;
cd645247 324 }
265a9e55 325 if (!NILP (current_buffer->abbrev_mode)
cd645247 326 && SYNTAX (c) != Sword
265a9e55 327 && NILP (current_buffer->read_only)
cd645247
JB
328 && point > BEGV && SYNTAX (FETCH_CHAR (point - 1)) == Sword)
329 {
ee8caabb 330 int modiff = MODIFF;
4c6e656f
RS
331 Fexpand_abbrev ();
332 /* We can't trust the value of Fexpand_abbrev,
ee8caabb
RS
333 but if Fexpand_abbrev changed the buffer,
334 assume it expanded something. */
335 if (MODIFF != modiff)
aa52fef9 336 hairy = 2;
cd645247
JB
337 }
338 if ((c == ' ' || c == '\n')
339 && !noautofill
265a9e55 340 && !NILP (current_buffer->auto_fill_function)
cd645247
JB
341 && current_column () > XFASTINT (current_buffer->fill_column))
342 {
343 if (c1 != '\n')
b9a7407f 344 insert_and_inherit (&c1, 1);
cd645247
JB
345 call0 (current_buffer->auto_fill_function);
346 if (c1 == '\n')
b9a7407f 347 insert_and_inherit (&c1, 1);
aa52fef9 348 hairy = 2;
cd645247
JB
349 }
350 else
b9a7407f 351 insert_and_inherit (&c1, 1);
cd645247
JB
352 synt = SYNTAX (c);
353 if ((synt == Sclose || synt == Smath)
265a9e55 354 && !NILP (Vblink_paren_function) && INTERACTIVE)
cd645247
JB
355 {
356 call0 (Vblink_paren_function);
aa52fef9 357 hairy = 2;
cd645247
JB
358 }
359 return hairy;
360}
361\f
362/* module initialization */
363
364syms_of_cmds ()
365{
366 Qkill_backward_chars = intern ("kill-backward-chars");
367 staticpro (&Qkill_backward_chars);
368
369 Qkill_forward_chars = intern ("kill-forward-chars");
370 staticpro (&Qkill_forward_chars);
371
6bbb0d4a
JB
372 Qoverwrite_mode_binary = intern ("overwrite-mode-binary");
373 staticpro (&Qoverwrite_mode_binary);
e686c647 374
cd645247
JB
375 DEFVAR_LISP ("blink-paren-function", &Vblink_paren_function,
376 "Function called, if non-nil, whenever a close parenthesis is inserted.\n\
377More precisely, a char with closeparen syntax is self-inserted.");
378 Vblink_paren_function = Qnil;
379
380 defsubr (&Sforward_char);
381 defsubr (&Sbackward_char);
382 defsubr (&Sforward_line);
383 defsubr (&Sbeginning_of_line);
384 defsubr (&Send_of_line);
385
386 defsubr (&Sdelete_char);
387 defsubr (&Sdelete_backward_char);
388
389 defsubr (&Sself_insert_command);
390 defsubr (&Snewline);
391}
392
393keys_of_cmds ()
394{
395 int n;
396
397 initial_define_key (global_map, Ctl('M'), "newline");
398 initial_define_key (global_map, Ctl('I'), "self-insert-command");
399 for (n = 040; n < 0177; n++)
400 initial_define_key (global_map, n, "self-insert-command");
cf9cdc11
RS
401#ifdef MSDOS
402 for (n = 0200; n < 0240; n++)
403 initial_define_key (global_map, n, "self-insert-command");
404#endif
94748cb9 405 for (n = 0240; n < 0400; n++)
eb46da6a 406 initial_define_key (global_map, n, "self-insert-command");
cd645247
JB
407
408 initial_define_key (global_map, Ctl ('A'), "beginning-of-line");
409 initial_define_key (global_map, Ctl ('B'), "backward-char");
410 initial_define_key (global_map, Ctl ('D'), "delete-char");
411 initial_define_key (global_map, Ctl ('E'), "end-of-line");
412 initial_define_key (global_map, Ctl ('F'), "forward-char");
413 initial_define_key (global_map, 0177, "delete-backward-char");
414}