]> code.delx.au - gnu-emacs/blob - src/cmds.c
(have_menus_p): Renamed from using_x_p.
[gnu-emacs] / src / cmds.c
1 /* Simple built-in editing commands.
2 Copyright (C) 1985, 1993, 1994, 1995 Free Software Foundation, Inc.
3
4 This file is part of GNU Emacs.
5
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.
10
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.
15
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. */
19
20
21 #include <config.h>
22 #include "lisp.h"
23 #include "commands.h"
24 #include "buffer.h"
25 #include "syntax.h"
26 #include "window.h"
27 #include "keyboard.h"
28
29 Lisp_Object Qkill_forward_chars, Qkill_backward_chars, Vblink_paren_function;
30
31 /* A possible value for a buffer's overwrite-mode variable. */
32 Lisp_Object Qoverwrite_mode_binary;
33
34 /* Non-nil means put this face on the next self-inserting character. */
35 Lisp_Object Vself_insert_face;
36
37 /* This is the command that set up Vself_insert_face. */
38 Lisp_Object Vself_insert_face_command;
39
40 extern Lisp_Object Qface;
41 \f
42 DEFUN ("forward-char", Fforward_char, Sforward_char, 0, 1, "p",
43 "Move point right ARG characters (left if ARG negative).\n\
44 On reaching end of buffer, stop and signal error.")
45 (arg)
46 Lisp_Object arg;
47 {
48 if (NILP (arg))
49 XSETFASTINT (arg, 1);
50 else
51 CHECK_NUMBER (arg, 0);
52
53 /* This used to just set point to point + XINT (arg), and then check
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 {
59 int new_point = point + XINT (arg);
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
75 return Qnil;
76 }
77
78 DEFUN ("backward-char", Fbackward_char, Sbackward_char, 0, 1, "p",
79 "Move point left ARG characters (right if ARG negative).\n\
80 On attempt to pass beginning or end of buffer, stop and signal error.")
81 (arg)
82 Lisp_Object arg;
83 {
84 if (NILP (arg))
85 XSETFASTINT (arg, 1);
86 else
87 CHECK_NUMBER (arg, 0);
88
89 XSETINT (arg, - XINT (arg));
90 return Fforward_char (arg);
91 }
92
93 DEFUN ("forward-line", Fforward_line, Sforward_line, 0, 1, "p",
94 "Move ARG lines forward (backward if ARG is negative).\n\
95 Precisely, if point is on line I, move to the start of line I + ARG.\n\
96 If there isn't room, go as far as possible (no error).\n\
97 Returns the count of lines left to move. If moving forward,\n\
98 that is ARG - number of lines moved; if backward, ARG + number moved.\n\
99 With 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
108 if (NILP (n))
109 count = 1;
110 else
111 {
112 CHECK_NUMBER (n, 0);
113 count = XINT (n);
114 }
115
116 negp = count <= 0;
117 pos = scan_buffer ('\n', pos2, 0, count - negp, &shortage, 1);
118 if (shortage > 0
119 && (negp
120 || (ZV > BEGV
121 && pos != pos2
122 && FETCH_CHAR (pos - 1) != '\n')))
123 shortage--;
124 SET_PT (pos);
125 return make_number (negp ? - shortage : shortage);
126 }
127
128 DEFUN ("beginning-of-line", Fbeginning_of_line, Sbeginning_of_line,
129 0, 1, "p",
130 "Move point to beginning of current line.\n\
131 With argument ARG not nil or 1, move forward ARG - 1 lines first.\n\
132 If scan reaches end of buffer, stop there without error.")
133 (n)
134 Lisp_Object n;
135 {
136 if (NILP (n))
137 XSETFASTINT (n, 1);
138 else
139 CHECK_NUMBER (n, 0);
140
141 Fforward_line (make_number (XINT (n) - 1));
142 return Qnil;
143 }
144
145 DEFUN ("end-of-line", Fend_of_line, Send_of_line,
146 0, 1, "p",
147 "Move point to end of current line.\n\
148 With argument ARG not nil or 1, move forward ARG - 1 lines first.\n\
149 If 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
156 if (NILP (n))
157 XSETFASTINT (n, 1);
158 else
159 CHECK_NUMBER (n, 0);
160
161 SET_PT (find_before_next_newline (PT, 0, XINT (n) - (XINT (n) <= 0)));
162
163 return Qnil;
164 }
165
166 DEFUN ("delete-char", Fdelete_char, Sdelete_char, 1, 2, "p\nP",
167 "Delete the following ARG characters (previous, with negative arg).\n\
168 Optional second arg KILLFLAG non-nil means kill instead (save in kill ring).\n\
169 Interactively, ARG is the prefix arg, and KILLFLAG is set if\n\
170 ARG was explicitly specified.")
171 (n, killflag)
172 Lisp_Object n, killflag;
173 {
174 CHECK_NUMBER (n, 0);
175
176 if (NILP (killflag))
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
200 DEFUN ("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\
203 Optional second arg KILLFLAG non-nil means kill instead (save in kill ring).\n\
204 Interactively, ARG is the prefix arg, and KILLFLAG is set if\n\
205 ARG 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
213 DEFUN ("self-insert-command", Fself_insert_command, Sself_insert_command, 1, 1, "p",
214 "Insert the character you type.\n\
215 Whichever 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. */
222 if (!INTEGERP (last_command_char))
223 bitch_at_user ();
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 }
236 else
237 while (XINT (arg) > 0)
238 {
239 /* Ok since old and new vals both nonneg */
240 XSETFASTINT (arg, XFASTINT (arg) - 1);
241 internal_self_insert (XINT (last_command_char), XFASTINT (arg) != 0);
242 }
243
244 return Qnil;
245 }
246
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),
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. */
253
254 internal_self_insert (c1, noautofill)
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;
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;
266 Lisp_Object overwrite;
267
268 overwrite = current_buffer->overwrite_mode;
269 if (!NILP (Vbefore_change_function) || !NILP (Vafter_change_function)
270 || !NILP (Vbefore_change_functions) || !NILP (Vafter_change_functions))
271 hairy = 1;
272
273 if (!NILP (overwrite)
274 && point < ZV
275 && (EQ (overwrite, Qoverwrite_mode_binary)
276 || (c != '\n' && FETCH_CHAR (point) != '\n'))
277 && (EQ (overwrite, Qoverwrite_mode_binary)
278 || FETCH_CHAR (point) != '\t'
279 || XINT (current_buffer->tab_width) <= 0
280 || XFASTINT (current_buffer->tab_width) > 20
281 || !((current_column () + 1) % XFASTINT (current_buffer->tab_width))))
282 {
283 del_range (point, point + 1);
284 hairy = 2;
285 }
286 if (!NILP (current_buffer->abbrev_mode)
287 && SYNTAX (c) != Sword
288 && NILP (current_buffer->read_only)
289 && point > BEGV && SYNTAX (FETCH_CHAR (point - 1)) == Sword)
290 {
291 int modiff = MODIFF;
292 Fexpand_abbrev ();
293 /* We can't trust the value of Fexpand_abbrev,
294 but if Fexpand_abbrev changed the buffer,
295 assume it expanded something. */
296 if (MODIFF != modiff)
297 hairy = 2;
298 }
299 if ((c == ' ' || c == '\n')
300 && !noautofill
301 && !NILP (current_buffer->auto_fill_function))
302 {
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);
309 call0 (current_buffer->auto_fill_function);
310 if (c1 == '\n')
311 SET_PT (point + 1);
312 hairy = 2;
313 }
314 else
315 insert_and_inherit (&c1, 1);
316
317 #ifdef HAVE_FACES
318 /* If previous command specified a face to use, use it. */
319 if (!NILP (Vself_insert_face)
320 && EQ (current_kboard->Vlast_command, Vself_insert_face_command))
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 }
328 #endif
329 synt = SYNTAX (c);
330 if ((synt == Sclose || synt == Smath)
331 && !NILP (Vblink_paren_function) && INTERACTIVE
332 && !noautofill)
333 {
334 call0 (Vblink_paren_function);
335 hairy = 2;
336 }
337 return hairy;
338 }
339 \f
340 /* module initialization */
341
342 syms_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
350 Qoverwrite_mode_binary = intern ("overwrite-mode-binary");
351 staticpro (&Qoverwrite_mode_binary);
352
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\
355 See 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\
360 If `last-command' does not equal this value, we ignore `self-insert-face'.");
361 Vself_insert_face_command = Qnil;
362
363 DEFVAR_LISP ("blink-paren-function", &Vblink_paren_function,
364 "Function called, if non-nil, whenever a close parenthesis is inserted.\n\
365 More 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);
378 }
379
380 keys_of_cmds ()
381 {
382 int n;
383
384 initial_define_key (global_map, Ctl ('I'), "self-insert-command");
385 for (n = 040; n < 0177; n++)
386 initial_define_key (global_map, n, "self-insert-command");
387 #ifdef MSDOS
388 for (n = 0200; n < 0240; n++)
389 initial_define_key (global_map, n, "self-insert-command");
390 #endif
391 for (n = 0240; n < 0400; n++)
392 initial_define_key (global_map, n, "self-insert-command");
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 }