(command_loop_1): Bind inhibit-quit to t when in Fsit_for.
[bpt/emacs.git] / src / cmds.c
CommitLineData
cd645247 1/* Simple built-in editing commands.
502ddf23 2 Copyright (C) 1985, 1992 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
21#include "config.h"
22#include "lisp.h"
23#include "commands.h"
24#include "buffer.h"
25#include "syntax.h"
26
27Lisp_Object Qkill_forward_chars, Qkill_backward_chars, Vblink_paren_function;
28
29\f
30DEFUN ("forward-char", Fforward_char, Sforward_char, 0, 1, "p",
31 "Move point right ARG characters (left if ARG negative).\n\
32On reaching end of buffer, stop and signal error.")
33 (n)
34 Lisp_Object n;
35{
265a9e55 36 if (NILP (n))
cd645247
JB
37 XFASTINT (n) = 1;
38 else
39 CHECK_NUMBER (n, 0);
40
41 SET_PT (point + XINT (n));
42 if (point < BEGV)
43 {
44 SET_PT (BEGV);
45 Fsignal (Qbeginning_of_buffer, Qnil);
46 }
47 if (point > ZV)
48 {
49 SET_PT (ZV);
50 Fsignal (Qend_of_buffer, Qnil);
51 }
52 return Qnil;
53}
54
55DEFUN ("backward-char", Fbackward_char, Sbackward_char, 0, 1, "p",
56 "Move point left ARG characters (right if ARG negative).\n\
57On attempt to pass beginning or end of buffer, stop and signal error.")
58 (n)
59 Lisp_Object n;
60{
265a9e55 61 if (NILP (n))
cd645247
JB
62 XFASTINT (n) = 1;
63 else
64 CHECK_NUMBER (n, 0);
65
66 XSETINT (n, - XINT (n));
67 return Fforward_char (n);
68}
69
70DEFUN ("forward-line", Fforward_line, Sforward_line, 0, 1, "p",
71 "Move ARG lines forward (backward if ARG is negative).\n\
72Precisely, if point is on line I, move to the start of line I + ARG.\n\
73If there isn't room, go as far as possible (no error).\n\
74Returns the count of lines left to move. If moving forward,\n\
75that is ARG - number of lines moved; if backward, ARG + number moved.\n\
76With positive ARG, a non-empty line at the end counts as one line\n\
77 successfully moved (for the return value).")
78 (n)
79 Lisp_Object n;
80{
81 int pos2 = point;
82 int pos;
83 int count, shortage, negp;
84
265a9e55 85 if (NILP (n))
cd645247
JB
86 count = 1;
87 else
88 {
89 CHECK_NUMBER (n, 0);
90 count = XINT (n);
91 }
92
93 negp = count <= 0;
94 pos = scan_buffer ('\n', pos2, count - negp, &shortage);
95 if (shortage > 0
96 && (negp
502ddf23
JB
97 || (ZV > BEGV
98 && pos != pos2
cd645247
JB
99 && FETCH_CHAR (pos - 1) != '\n')))
100 shortage--;
101 SET_PT (pos);
102 return make_number (negp ? - shortage : shortage);
103}
104
105DEFUN ("beginning-of-line", Fbeginning_of_line, Sbeginning_of_line,
106 0, 1, "p",
107 "Move point to beginning of current line.\n\
108With argument ARG not nil or 1, move forward ARG - 1 lines first.\n\
109If scan reaches end of buffer, stop there without error.")
110 (n)
111 Lisp_Object n;
112{
265a9e55 113 if (NILP (n))
cd645247
JB
114 XFASTINT (n) = 1;
115 else
116 CHECK_NUMBER (n, 0);
117
118 Fforward_line (make_number (XINT (n) - 1));
119 return Qnil;
120}
121
122DEFUN ("end-of-line", Fend_of_line, Send_of_line,
123 0, 1, "p",
124 "Move point to end of current line.\n\
125With argument ARG not nil or 1, move forward ARG - 1 lines first.\n\
126If scan reaches end of buffer, stop there without error.")
127 (n)
128 Lisp_Object n;
129{
130 register int pos;
131 register int stop;
132
265a9e55 133 if (NILP (n))
cd645247
JB
134 XFASTINT (n) = 1;
135 else
136 CHECK_NUMBER (n, 0);
137
138 if (XINT (n) != 1)
139 Fforward_line (make_number (XINT (n) - 1));
140
141 pos = point;
142 stop = ZV;
143 while (pos < stop && FETCH_CHAR (pos) != '\n') pos++;
144 SET_PT (pos);
145
146 return Qnil;
147}
148
149DEFUN ("delete-char", Fdelete_char, Sdelete_char, 1, 2, "p\nP",
150 "Delete the following ARG characters (previous, with negative arg).\n\
151Optional second arg KILLFLAG non-nil means kill instead (save in kill ring).\n\
152Interactively, ARG is the prefix arg, and KILLFLAG is set if\n\
153ARG was explicitly specified.")
154 (n, killflag)
155 Lisp_Object n, killflag;
156{
157 CHECK_NUMBER (n, 0);
158
265a9e55 159 if (NILP (killflag))
cd645247
JB
160 {
161 if (XINT (n) < 0)
162 {
163 if (point + XINT (n) < BEGV)
164 Fsignal (Qbeginning_of_buffer, Qnil);
165 else
166 del_range (point + XINT (n), point);
167 }
168 else
169 {
170 if (point + XINT (n) > ZV)
171 Fsignal (Qend_of_buffer, Qnil);
172 else
173 del_range (point, point + XINT (n));
174 }
175 }
176 else
177 {
178 call1 (Qkill_forward_chars, n);
179 }
180 return Qnil;
181}
182
183DEFUN ("delete-backward-char", Fdelete_backward_char, Sdelete_backward_char,
184 1, 2, "p\nP",
185 "Delete the previous ARG characters (following, with negative ARG).\n\
186Optional second arg KILLFLAG non-nil means kill instead (save in kill ring).\n\
187Interactively, ARG is the prefix arg, and KILLFLAG is set if\n\
188ARG was explicitly specified.")
189 (n, killflag)
190 Lisp_Object n, killflag;
191{
192 CHECK_NUMBER (n, 0);
193 return Fdelete_char (make_number (-XINT (n)), killflag);
194}
195
196DEFUN ("self-insert-command", Fself_insert_command, Sself_insert_command, 1, 1, "p",
197 "Insert the character you type.\n\
198Whichever character you type to run this command is inserted.")
199 (arg)
200 Lisp_Object arg;
201{
202 CHECK_NUMBER (arg, 0);
203
204 /* Barf if the key that invoked this was not a character. */
205 if (XTYPE (last_command_char) != Lisp_Int)
206 bitch_at_user ();
207 else
208 while (XINT (arg) > 0)
209 {
210 XFASTINT (arg)--; /* Ok since old and new vals both nonneg */
211 internal_self_insert (XINT (last_command_char), XFASTINT (arg) != 0);
212 }
213
214 return Qnil;
215}
216
217DEFUN ("newline", Fnewline, Snewline, 0, 1, "P",
218 "Insert a newline. With arg, insert that many newlines.\n\
219In Auto Fill mode, if no numeric arg, break the preceding line if it's long.")
220 (arg1)
221 Lisp_Object arg1;
222{
223 int flag;
224 Lisp_Object arg;
225 char c1 = '\n';
226
227 arg = Fprefix_numeric_value (arg1);
228
265a9e55 229 if (!NILP (current_buffer->read_only))
cd645247
JB
230 Fsignal (Qbuffer_read_only, Qnil);
231
232 /* Inserting a newline at the end of a line
233 produces better redisplay in try_window_id
234 than inserting at the ebginning fo a line,
235 And the textual result is the same.
236 So if at beginning, pretend to be at the end.
237 Must avoid internal_self_insert in that case since point is wrong.
238 Luckily internal_self_insert's special features all do nothing in that case. */
239
240 flag = point > BEGV && FETCH_CHAR (point - 1) == '\n';
241 if (flag)
242 SET_PT (point - 1);
243
244 while (XINT (arg) > 0)
245 {
246 if (flag)
247 insert (&c1, 1);
248 else
265a9e55 249 internal_self_insert ('\n', !NILP (arg1));
cd645247
JB
250 XFASTINT (arg)--; /* Ok since old and new vals both nonneg */
251 }
252
253 if (flag)
254 SET_PT (point + 1);
255
256 return Qnil;
257}
258
4c6e656f
RS
259/* Insert character C1. If NOAUTOFILL is nonzero, don't do autofill
260 even if it is enabled.
261
262 If this insertion is suitable for direct output (completely simple),
263 return 0. A value of 1 indicates this *might* not have been simple. */
264
cd645247
JB
265internal_self_insert (c1, noautofill)
266 char c1;
267 int noautofill;
268{
269 extern Lisp_Object Fexpand_abbrev ();
270 int hairy = 0;
271 Lisp_Object tem;
272 register enum syntaxcode synt;
273 register int c = c1;
274
265a9e55 275 if (!NILP (Vbefore_change_function) || !NILP (Vafter_change_function))
cd645247
JB
276 hairy = 1;
277
265a9e55 278 if (!NILP (current_buffer->overwrite_mode)
cd645247
JB
279 && point < ZV
280 && c != '\n' && FETCH_CHAR (point) != '\n'
281 && (FETCH_CHAR (point) != '\t'
282 || XINT (current_buffer->tab_width) <= 0
283 || !((current_column () + 1) % XFASTINT (current_buffer->tab_width))))
284 {
285 del_range (point, point + 1);
286 hairy = 1;
287 }
265a9e55 288 if (!NILP (current_buffer->abbrev_mode)
cd645247 289 && SYNTAX (c) != Sword
265a9e55 290 && NILP (current_buffer->read_only)
cd645247
JB
291 && point > BEGV && SYNTAX (FETCH_CHAR (point - 1)) == Sword)
292 {
4c6e656f
RS
293 Fexpand_abbrev ();
294 /* We can't trust the value of Fexpand_abbrev,
295 but if the buffer is now changed, this is "hairy"
296 and not suitable for direct output. */
297 if (MODIFF <= current_buffer->save_modified)
cd645247
JB
298 hairy = 1;
299 }
300 if ((c == ' ' || c == '\n')
301 && !noautofill
265a9e55 302 && !NILP (current_buffer->auto_fill_function)
cd645247
JB
303 && current_column () > XFASTINT (current_buffer->fill_column))
304 {
305 if (c1 != '\n')
306 insert (&c1, 1);
307 call0 (current_buffer->auto_fill_function);
308 if (c1 == '\n')
309 insert (&c1, 1);
310 hairy = 1;
311 }
312 else
313 insert (&c1, 1);
314 synt = SYNTAX (c);
315 if ((synt == Sclose || synt == Smath)
265a9e55 316 && !NILP (Vblink_paren_function) && INTERACTIVE)
cd645247
JB
317 {
318 call0 (Vblink_paren_function);
319 hairy = 1;
320 }
321 return hairy;
322}
323\f
324/* module initialization */
325
326syms_of_cmds ()
327{
328 Qkill_backward_chars = intern ("kill-backward-chars");
329 staticpro (&Qkill_backward_chars);
330
331 Qkill_forward_chars = intern ("kill-forward-chars");
332 staticpro (&Qkill_forward_chars);
333
334 DEFVAR_LISP ("blink-paren-function", &Vblink_paren_function,
335 "Function called, if non-nil, whenever a close parenthesis is inserted.\n\
336More precisely, a char with closeparen syntax is self-inserted.");
337 Vblink_paren_function = Qnil;
338
339 defsubr (&Sforward_char);
340 defsubr (&Sbackward_char);
341 defsubr (&Sforward_line);
342 defsubr (&Sbeginning_of_line);
343 defsubr (&Send_of_line);
344
345 defsubr (&Sdelete_char);
346 defsubr (&Sdelete_backward_char);
347
348 defsubr (&Sself_insert_command);
349 defsubr (&Snewline);
350}
351
352keys_of_cmds ()
353{
354 int n;
355
356 initial_define_key (global_map, Ctl('M'), "newline");
357 initial_define_key (global_map, Ctl('I'), "self-insert-command");
358 for (n = 040; n < 0177; n++)
359 initial_define_key (global_map, n, "self-insert-command");
360
361 initial_define_key (global_map, Ctl ('A'), "beginning-of-line");
362 initial_define_key (global_map, Ctl ('B'), "backward-char");
363 initial_define_key (global_map, Ctl ('D'), "delete-char");
364 initial_define_key (global_map, Ctl ('E'), "end-of-line");
365 initial_define_key (global_map, Ctl ('F'), "forward-char");
366 initial_define_key (global_map, 0177, "delete-backward-char");
367}