* floatfns.c (Flogb): Always implement this by calling Flog, even
[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 {
ee8caabb 293 int modiff = MODIFF;
4c6e656f
RS
294 Fexpand_abbrev ();
295 /* We can't trust the value of Fexpand_abbrev,
ee8caabb
RS
296 but if Fexpand_abbrev changed the buffer,
297 assume it expanded something. */
298 if (MODIFF != modiff)
cd645247
JB
299 hairy = 1;
300 }
301 if ((c == ' ' || c == '\n')
302 && !noautofill
265a9e55 303 && !NILP (current_buffer->auto_fill_function)
cd645247
JB
304 && current_column () > XFASTINT (current_buffer->fill_column))
305 {
306 if (c1 != '\n')
307 insert (&c1, 1);
308 call0 (current_buffer->auto_fill_function);
309 if (c1 == '\n')
310 insert (&c1, 1);
311 hairy = 1;
312 }
313 else
314 insert (&c1, 1);
315 synt = SYNTAX (c);
316 if ((synt == Sclose || synt == Smath)
265a9e55 317 && !NILP (Vblink_paren_function) && INTERACTIVE)
cd645247
JB
318 {
319 call0 (Vblink_paren_function);
320 hairy = 1;
321 }
322 return hairy;
323}
324\f
325/* module initialization */
326
327syms_of_cmds ()
328{
329 Qkill_backward_chars = intern ("kill-backward-chars");
330 staticpro (&Qkill_backward_chars);
331
332 Qkill_forward_chars = intern ("kill-forward-chars");
333 staticpro (&Qkill_forward_chars);
334
335 DEFVAR_LISP ("blink-paren-function", &Vblink_paren_function,
336 "Function called, if non-nil, whenever a close parenthesis is inserted.\n\
337More precisely, a char with closeparen syntax is self-inserted.");
338 Vblink_paren_function = Qnil;
339
340 defsubr (&Sforward_char);
341 defsubr (&Sbackward_char);
342 defsubr (&Sforward_line);
343 defsubr (&Sbeginning_of_line);
344 defsubr (&Send_of_line);
345
346 defsubr (&Sdelete_char);
347 defsubr (&Sdelete_backward_char);
348
349 defsubr (&Sself_insert_command);
350 defsubr (&Snewline);
351}
352
353keys_of_cmds ()
354{
355 int n;
356
357 initial_define_key (global_map, Ctl('M'), "newline");
358 initial_define_key (global_map, Ctl('I'), "self-insert-command");
359 for (n = 040; n < 0177; n++)
360 initial_define_key (global_map, n, "self-insert-command");
361
362 initial_define_key (global_map, Ctl ('A'), "beginning-of-line");
363 initial_define_key (global_map, Ctl ('B'), "backward-char");
364 initial_define_key (global_map, Ctl ('D'), "delete-char");
365 initial_define_key (global_map, Ctl ('E'), "end-of-line");
366 initial_define_key (global_map, Ctl ('F'), "forward-char");
367 initial_define_key (global_map, 0177, "delete-backward-char");
368}