(x_set_cursor_type): Set cursor_width field.
[emacs.git] / src / cmds.c
blobabad2cf63af603a8cd084b419d6a2d2aac32e03f
1 /* Simple built-in editing commands.
2 Copyright (C) 1985, 1993, 1994 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
21 #include <config.h>
22 #include "lisp.h"
23 #include "commands.h"
24 #include "buffer.h"
25 #include "syntax.h"
26 #include "window.h"
28 Lisp_Object Qkill_forward_chars, Qkill_backward_chars, Vblink_paren_function;
29 Lisp_Object Vuse_hard_newlines;
31 /* A possible value for a buffer's overwrite-mode variable. */
32 Lisp_Object Qoverwrite_mode_binary;
34 /* Non-nil means put this face on the next self-inserting character. */
35 Lisp_Object Vself_insert_face;
37 /* This is the command that set up Vself_insert_face. */
38 Lisp_Object Vself_insert_face_command;
40 #ifdef USE_TEXT_PROPERTIES
41 Lisp_Object Qhard;
42 #endif
44 extern Lisp_Object Qface;
46 DEFUN ("forward-char", Fforward_char, Sforward_char, 0, 1, "p",
47 "Move point right ARG characters (left if ARG negative).\n\
48 On reaching end of buffer, stop and signal error.")
49 (n)
50 Lisp_Object n;
52 if (NILP (n))
53 XSETFASTINT (n, 1);
54 else
55 CHECK_NUMBER (n, 0);
57 /* This used to just set point to point + XINT (n), and then check
58 to see if it was within boundaries. But now that SET_PT can
59 potentially do a lot of stuff (calling entering and exiting
60 hooks, etcetera), that's not a good approach. So we validate the
61 proposed position, then set point. */
63 int new_point = point + XINT (n);
65 if (new_point < BEGV)
67 SET_PT (BEGV);
68 Fsignal (Qbeginning_of_buffer, Qnil);
70 if (new_point > ZV)
72 SET_PT (ZV);
73 Fsignal (Qend_of_buffer, Qnil);
76 SET_PT (new_point);
79 return Qnil;
82 DEFUN ("backward-char", Fbackward_char, Sbackward_char, 0, 1, "p",
83 "Move point left ARG characters (right if ARG negative).\n\
84 On attempt to pass beginning or end of buffer, stop and signal error.")
85 (n)
86 Lisp_Object n;
88 if (NILP (n))
89 XSETFASTINT (n, 1);
90 else
91 CHECK_NUMBER (n, 0);
93 XSETINT (n, - XINT (n));
94 return Fforward_char (n);
97 DEFUN ("forward-line", Fforward_line, Sforward_line, 0, 1, "p",
98 "Move ARG lines forward (backward if ARG is negative).\n\
99 Precisely, if point is on line I, move to the start of line I + ARG.\n\
100 If there isn't room, go as far as possible (no error).\n\
101 Returns the count of lines left to move. If moving forward,\n\
102 that is ARG - number of lines moved; if backward, ARG + number moved.\n\
103 With positive ARG, a non-empty line at the end counts as one line\n\
104 successfully moved (for the return value).")
106 Lisp_Object n;
108 int pos2 = point;
109 int pos;
110 int count, shortage, negp;
112 if (NILP (n))
113 count = 1;
114 else
116 CHECK_NUMBER (n, 0);
117 count = XINT (n);
120 negp = count <= 0;
121 pos = scan_buffer ('\n', pos2, 0, count - negp, &shortage, 1);
122 if (shortage > 0
123 && (negp
124 || (ZV > BEGV
125 && pos != pos2
126 && FETCH_CHAR (pos - 1) != '\n')))
127 shortage--;
128 SET_PT (pos);
129 return make_number (negp ? - shortage : shortage);
132 DEFUN ("beginning-of-line", Fbeginning_of_line, Sbeginning_of_line,
133 0, 1, "p",
134 "Move point to beginning of current line.\n\
135 With argument ARG not nil or 1, move forward ARG - 1 lines first.\n\
136 If scan reaches end of buffer, stop there without error.")
138 Lisp_Object n;
140 if (NILP (n))
141 XSETFASTINT (n, 1);
142 else
143 CHECK_NUMBER (n, 0);
145 Fforward_line (make_number (XINT (n) - 1));
146 return Qnil;
149 DEFUN ("end-of-line", Fend_of_line, Send_of_line,
150 0, 1, "p",
151 "Move point to end of current line.\n\
152 With argument ARG not nil or 1, move forward ARG - 1 lines first.\n\
153 If scan reaches end of buffer, stop there without error.")
155 Lisp_Object n;
157 register int pos;
158 register int stop;
160 if (NILP (n))
161 XSETFASTINT (n, 1);
162 else
163 CHECK_NUMBER (n, 0);
165 SET_PT (find_before_next_newline (PT, 0, XINT (n) - (XINT (n) <= 0)));
167 return Qnil;
170 DEFUN ("delete-char", Fdelete_char, Sdelete_char, 1, 2, "p\nP",
171 "Delete the following ARG characters (previous, with negative arg).\n\
172 Optional second arg KILLFLAG non-nil means kill instead (save in kill ring).\n\
173 Interactively, ARG is the prefix arg, and KILLFLAG is set if\n\
174 ARG was explicitly specified.")
175 (n, killflag)
176 Lisp_Object n, killflag;
178 CHECK_NUMBER (n, 0);
180 if (NILP (killflag))
182 if (XINT (n) < 0)
184 if (point + XINT (n) < BEGV)
185 Fsignal (Qbeginning_of_buffer, Qnil);
186 else
187 del_range (point + XINT (n), point);
189 else
191 if (point + XINT (n) > ZV)
192 Fsignal (Qend_of_buffer, Qnil);
193 else
194 del_range (point, point + XINT (n));
197 else
199 call1 (Qkill_forward_chars, n);
201 return Qnil;
204 DEFUN ("delete-backward-char", Fdelete_backward_char, Sdelete_backward_char,
205 1, 2, "p\nP",
206 "Delete the previous ARG characters (following, with negative ARG).\n\
207 Optional second arg KILLFLAG non-nil means kill instead (save in kill ring).\n\
208 Interactively, ARG is the prefix arg, and KILLFLAG is set if\n\
209 ARG was explicitly specified.")
210 (n, killflag)
211 Lisp_Object n, killflag;
213 CHECK_NUMBER (n, 0);
214 return Fdelete_char (make_number (-XINT (n)), killflag);
217 DEFUN ("self-insert-command", Fself_insert_command, Sself_insert_command, 1, 1, "p",
218 "Insert the character you type.\n\
219 Whichever character you type to run this command is inserted.")
220 (arg)
221 Lisp_Object arg;
223 CHECK_NUMBER (arg, 0);
225 /* Barf if the key that invoked this was not a character. */
226 if (!INTEGERP (last_command_char))
227 bitch_at_user ();
228 else
229 while (XINT (arg) > 0)
231 /* Ok since old and new vals both nonneg */
232 XSETFASTINT (arg, XFASTINT (arg) - 1);
233 internal_self_insert (XINT (last_command_char), XFASTINT (arg) != 0);
236 return Qnil;
239 DEFUN ("newline", Fnewline, Snewline, 0, 1, "P",
240 "Insert a newline. With arg, insert that many newlines.\n\
241 In Auto Fill mode, if no numeric arg, break the preceding line if it's long.")
242 (arg1)
243 Lisp_Object arg1;
245 int flag, i;
246 Lisp_Object arg;
247 char c1 = '\n';
249 arg = Fprefix_numeric_value (arg1);
251 if (!NILP (current_buffer->read_only))
252 Fbarf_if_buffer_read_only ();
254 /* Inserting a newline at the end of a line produces better
255 redisplay in try_window_id than inserting at the beginning of a
256 line, and the textual result is the same. So, if we're at
257 beginning of line, pretend to be at the end of the previous line.
259 We can't use internal_self_insert in that case since it won't do
260 the insertion correctly. Luckily, internal_self_insert's special
261 features all do nothing in that case. */
263 flag = point > BEGV && FETCH_CHAR (point - 1) == '\n';
264 /* Don't do this if at the beginning of the window. */
265 if (XBUFFER (XWINDOW (selected_window)->buffer) == current_buffer
266 && marker_position (XWINDOW (selected_window)->start) == PT)
267 flag = 0;
269 #ifdef USE_TEXT_PROPERTIES
270 /* We cannot use this optimization if properties change
271 in the vicinity.
272 ??? We need to check for change hook properties, etc. */
273 if (flag)
274 if (! (point - 1 > BEGV && ! property_change_between_p (point - 2, point)))
275 flag = 0;
276 #endif
278 if (flag)
279 SET_PT (point - 1);
281 for (i = XINT (arg); i > 0; i--)
283 if (flag)
284 insert_and_inherit (&c1, 1);
285 else
286 internal_self_insert ('\n', !NILP (arg1));
289 #ifdef USE_TEXT_PROPERTIES
290 if (Vuse_hard_newlines)
292 Lisp_Object from, to, sticky;
293 XSETFASTINT (from, PT - arg);
294 XSETFASTINT (to, PT);
295 Fput_text_property (from, to, Qhard, Qt, Qnil);
296 /* If rear_nonsticky is not "t", locally add Qhard to the list. */
297 sticky = Fget_text_property (from, Qrear_nonsticky, Qnil);
298 if (NILP (sticky)
299 || (CONSP (sticky) && NILP (Fmemq (Qhard, sticky))))
301 sticky = Fcons (Qhard, sticky);
302 Fput_text_property (from, to, Qrear_nonsticky, sticky, Qnil);
305 #endif
308 if (flag)
309 SET_PT (point + 1);
311 return Qnil;
314 /* Insert character C1. If NOAUTOFILL is nonzero, don't do autofill
315 even if it is enabled.
317 If this insertion is suitable for direct output (completely simple),
318 return 0. A value of 1 indicates this *might* not have been simple.
319 A value of 2 means this did things that call for an undo boundary. */
321 internal_self_insert (c1, noautofill)
322 char c1;
323 int noautofill;
325 extern Lisp_Object Fexpand_abbrev ();
326 int hairy = 0;
327 Lisp_Object tem;
328 register enum syntaxcode synt;
329 register int c = c1;
330 Lisp_Object overwrite;
332 overwrite = current_buffer->overwrite_mode;
333 if (!NILP (Vbefore_change_function) || !NILP (Vafter_change_function)
334 || !NILP (Vbefore_change_functions) || !NILP (Vafter_change_functions))
335 hairy = 1;
337 if (!NILP (overwrite)
338 && point < ZV
339 && (EQ (overwrite, Qoverwrite_mode_binary)
340 || (c != '\n' && FETCH_CHAR (point) != '\n'))
341 && (EQ (overwrite, Qoverwrite_mode_binary)
342 || FETCH_CHAR (point) != '\t'
343 || XINT (current_buffer->tab_width) <= 0
344 || XFASTINT (current_buffer->tab_width) > 20
345 || !((current_column () + 1) % XFASTINT (current_buffer->tab_width))))
347 del_range (point, point + 1);
348 hairy = 2;
350 if (!NILP (current_buffer->abbrev_mode)
351 && SYNTAX (c) != Sword
352 && NILP (current_buffer->read_only)
353 && point > BEGV && SYNTAX (FETCH_CHAR (point - 1)) == Sword)
355 int modiff = MODIFF;
356 Fexpand_abbrev ();
357 /* We can't trust the value of Fexpand_abbrev,
358 but if Fexpand_abbrev changed the buffer,
359 assume it expanded something. */
360 if (MODIFF != modiff)
361 hairy = 2;
363 if ((c == ' ' || c == '\n')
364 && !noautofill
365 && !NILP (current_buffer->auto_fill_function))
367 if (c1 != '\n')
368 insert_and_inherit (&c1, 1);
369 call0 (current_buffer->auto_fill_function);
370 if (c1 == '\n')
371 insert_and_inherit (&c1, 1);
372 hairy = 2;
374 else
375 insert_and_inherit (&c1, 1);
377 /* If previous command specified a face to use, use it. */
378 if (!NILP (Vself_insert_face)
379 && EQ (last_command, Vself_insert_face_command))
381 Lisp_Object before, after;
382 XSETINT (before, PT - 1);
383 XSETINT (after, PT);
384 Fput_text_property (before, after, Qface, Vself_insert_face, Qnil);
385 Vself_insert_face = Qnil;
387 synt = SYNTAX (c);
388 if ((synt == Sclose || synt == Smath)
389 && !NILP (Vblink_paren_function) && INTERACTIVE)
391 call0 (Vblink_paren_function);
392 hairy = 2;
394 return hairy;
397 /* module initialization */
399 syms_of_cmds ()
401 Qkill_backward_chars = intern ("kill-backward-chars");
402 staticpro (&Qkill_backward_chars);
404 Qkill_forward_chars = intern ("kill-forward-chars");
405 staticpro (&Qkill_forward_chars);
407 Qoverwrite_mode_binary = intern ("overwrite-mode-binary");
408 staticpro (&Qoverwrite_mode_binary);
410 Qhard = intern ("hard");
411 staticpro (&Qhard);
413 DEFVAR_BOOL ("use-hard-newlines", &Vuse_hard_newlines,
414 "Non-nil means to distinguish hard and soft newlines.\n\
415 When this is non-nil, the functions `newline' and `open-line' add the\n\
416 text-property `hard' to newlines that they insert. Also, a line is\n\
417 only considered as a candidate to match `paragraph-start' or\n\
418 `paragraph-separate' if it follows a hard newline. Newlines not\n\
419 marked hard are called \"soft\", and are always internal to\n\
420 paragraphs. The fill functions always insert soft newlines.");
421 Vuse_hard_newlines = 0;
423 DEFVAR_LISP ("self-insert-face", &Vself_insert_face,
424 "If non-nil, set the face of the next self-inserting character to this.\n\
425 See also `self-insert-face-command'.");
426 Vself_insert_face = Qnil;
428 DEFVAR_LISP ("self-insert-face-command", &Vself_insert_face_command,
429 "This is the command that set up `self-insert-face'.\n\
430 If `last-command' does not equal this value, we ignore `self-insert-face'.");
431 Vself_insert_face_command = Qnil;
433 DEFVAR_LISP ("blink-paren-function", &Vblink_paren_function,
434 "Function called, if non-nil, whenever a close parenthesis is inserted.\n\
435 More precisely, a char with closeparen syntax is self-inserted.");
436 Vblink_paren_function = Qnil;
438 defsubr (&Sforward_char);
439 defsubr (&Sbackward_char);
440 defsubr (&Sforward_line);
441 defsubr (&Sbeginning_of_line);
442 defsubr (&Send_of_line);
444 defsubr (&Sdelete_char);
445 defsubr (&Sdelete_backward_char);
447 defsubr (&Sself_insert_command);
448 defsubr (&Snewline);
451 keys_of_cmds ()
453 int n;
455 initial_define_key (global_map, Ctl ('M'), "newline");
456 initial_define_key (global_map, Ctl ('I'), "self-insert-command");
457 for (n = 040; n < 0177; n++)
458 initial_define_key (global_map, n, "self-insert-command");
459 #ifdef MSDOS
460 for (n = 0200; n < 0240; n++)
461 initial_define_key (global_map, n, "self-insert-command");
462 #endif
463 for (n = 0240; n < 0400; n++)
464 initial_define_key (global_map, n, "self-insert-command");
466 initial_define_key (global_map, Ctl ('A'), "beginning-of-line");
467 initial_define_key (global_map, Ctl ('B'), "backward-char");
468 initial_define_key (global_map, Ctl ('D'), "delete-char");
469 initial_define_key (global_map, Ctl ('E'), "end-of-line");
470 initial_define_key (global_map, Ctl ('F'), "forward-char");
471 initial_define_key (global_map, 0177, "delete-backward-char");