]> code.delx.au - gnu-emacs/blob - src/cmds.c
(make-comint): Error, if start-process is not fboundp.
[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
28 Lisp_Object Qkill_forward_chars, Qkill_backward_chars, Vblink_paren_function;
29
30 /* A possible value for a buffer's overwrite-mode variable. */
31 Lisp_Object Qoverwrite_mode_binary;
32
33 /* Non-nil means put this face on the next self-inserting character. */
34 Lisp_Object Vself_insert_face;
35
36 /* This is the command that set up Vself_insert_face. */
37 Lisp_Object Vself_insert_face_command;
38
39 extern Lisp_Object Qface;
40 \f
41 DEFUN ("forward-char", Fforward_char, Sforward_char, 0, 1, "p",
42 "Move point right ARG characters (left if ARG negative).\n\
43 On reaching end of buffer, stop and signal error.")
44 (n)
45 Lisp_Object n;
46 {
47 if (NILP (n))
48 XSETFASTINT (n, 1);
49 else
50 CHECK_NUMBER (n, 0);
51
52 /* This used to just set point to point + XINT (n), and then check
53 to see if it was within boundaries. But now that SET_PT can
54 potentially do a lot of stuff (calling entering and exiting
55 hooks, etcetera), that's not a good approach. So we validate the
56 proposed position, then set point. */
57 {
58 int new_point = point + XINT (n);
59
60 if (new_point < BEGV)
61 {
62 SET_PT (BEGV);
63 Fsignal (Qbeginning_of_buffer, Qnil);
64 }
65 if (new_point > ZV)
66 {
67 SET_PT (ZV);
68 Fsignal (Qend_of_buffer, Qnil);
69 }
70
71 SET_PT (new_point);
72 }
73
74 return Qnil;
75 }
76
77 DEFUN ("backward-char", Fbackward_char, Sbackward_char, 0, 1, "p",
78 "Move point left ARG characters (right if ARG negative).\n\
79 On attempt to pass beginning or end of buffer, stop and signal error.")
80 (n)
81 Lisp_Object n;
82 {
83 if (NILP (n))
84 XSETFASTINT (n, 1);
85 else
86 CHECK_NUMBER (n, 0);
87
88 XSETINT (n, - XINT (n));
89 return Fforward_char (n);
90 }
91
92 DEFUN ("forward-line", Fforward_line, Sforward_line, 0, 1, "p",
93 "Move ARG lines forward (backward if ARG is negative).\n\
94 Precisely, if point is on line I, move to the start of line I + ARG.\n\
95 If there isn't room, go as far as possible (no error).\n\
96 Returns the count of lines left to move. If moving forward,\n\
97 that is ARG - number of lines moved; if backward, ARG + number moved.\n\
98 With positive ARG, a non-empty line at the end counts as one line\n\
99 successfully moved (for the return value).")
100 (n)
101 Lisp_Object n;
102 {
103 int pos2 = point;
104 int pos;
105 int count, shortage, negp;
106
107 if (NILP (n))
108 count = 1;
109 else
110 {
111 CHECK_NUMBER (n, 0);
112 count = XINT (n);
113 }
114
115 negp = count <= 0;
116 pos = scan_buffer ('\n', pos2, 0, count - negp, &shortage, 1);
117 if (shortage > 0
118 && (negp
119 || (ZV > BEGV
120 && pos != pos2
121 && FETCH_CHAR (pos - 1) != '\n')))
122 shortage--;
123 SET_PT (pos);
124 return make_number (negp ? - shortage : shortage);
125 }
126
127 DEFUN ("beginning-of-line", Fbeginning_of_line, Sbeginning_of_line,
128 0, 1, "p",
129 "Move point to beginning of current line.\n\
130 With argument ARG not nil or 1, move forward ARG - 1 lines first.\n\
131 If scan reaches end of buffer, stop there without error.")
132 (n)
133 Lisp_Object n;
134 {
135 if (NILP (n))
136 XSETFASTINT (n, 1);
137 else
138 CHECK_NUMBER (n, 0);
139
140 Fforward_line (make_number (XINT (n) - 1));
141 return Qnil;
142 }
143
144 DEFUN ("end-of-line", Fend_of_line, Send_of_line,
145 0, 1, "p",
146 "Move point to end of current line.\n\
147 With argument ARG not nil or 1, move forward ARG - 1 lines first.\n\
148 If scan reaches end of buffer, stop there without error.")
149 (n)
150 Lisp_Object n;
151 {
152 register int pos;
153 register int stop;
154
155 if (NILP (n))
156 XSETFASTINT (n, 1);
157 else
158 CHECK_NUMBER (n, 0);
159
160 SET_PT (find_before_next_newline (PT, 0, XINT (n) - (XINT (n) <= 0)));
161
162 return Qnil;
163 }
164
165 DEFUN ("delete-char", Fdelete_char, Sdelete_char, 1, 2, "p\nP",
166 "Delete the following ARG characters (previous, with negative arg).\n\
167 Optional second arg KILLFLAG non-nil means kill instead (save in kill ring).\n\
168 Interactively, ARG is the prefix arg, and KILLFLAG is set if\n\
169 ARG was explicitly specified.")
170 (n, killflag)
171 Lisp_Object n, killflag;
172 {
173 CHECK_NUMBER (n, 0);
174
175 if (NILP (killflag))
176 {
177 if (XINT (n) < 0)
178 {
179 if (point + XINT (n) < BEGV)
180 Fsignal (Qbeginning_of_buffer, Qnil);
181 else
182 del_range (point + XINT (n), point);
183 }
184 else
185 {
186 if (point + XINT (n) > ZV)
187 Fsignal (Qend_of_buffer, Qnil);
188 else
189 del_range (point, point + XINT (n));
190 }
191 }
192 else
193 {
194 call1 (Qkill_forward_chars, n);
195 }
196 return Qnil;
197 }
198
199 DEFUN ("delete-backward-char", Fdelete_backward_char, Sdelete_backward_char,
200 1, 2, "p\nP",
201 "Delete the previous ARG characters (following, with negative ARG).\n\
202 Optional second arg KILLFLAG non-nil means kill instead (save in kill ring).\n\
203 Interactively, ARG is the prefix arg, and KILLFLAG is set if\n\
204 ARG was explicitly specified.")
205 (n, killflag)
206 Lisp_Object n, killflag;
207 {
208 CHECK_NUMBER (n, 0);
209 return Fdelete_char (make_number (-XINT (n)), killflag);
210 }
211
212 DEFUN ("self-insert-command", Fself_insert_command, Sself_insert_command, 1, 1, "p",
213 "Insert the character you type.\n\
214 Whichever character you type to run this command is inserted.")
215 (arg)
216 Lisp_Object arg;
217 {
218 CHECK_NUMBER (arg, 0);
219
220 /* Barf if the key that invoked this was not a character. */
221 if (!INTEGERP (last_command_char))
222 bitch_at_user ();
223 else
224 while (XINT (arg) > 0)
225 {
226 /* Ok since old and new vals both nonneg */
227 XSETFASTINT (arg, XFASTINT (arg) - 1);
228 internal_self_insert (XINT (last_command_char), XFASTINT (arg) != 0);
229 }
230
231 return Qnil;
232 }
233
234 /* Insert character C1. If NOAUTOFILL is nonzero, don't do autofill
235 even if it is enabled.
236
237 If this insertion is suitable for direct output (completely simple),
238 return 0. A value of 1 indicates this *might* not have been simple.
239 A value of 2 means this did things that call for an undo boundary. */
240
241 internal_self_insert (c1, noautofill)
242 char c1;
243 int noautofill;
244 {
245 extern Lisp_Object Fexpand_abbrev ();
246 int hairy = 0;
247 Lisp_Object tem;
248 register enum syntaxcode synt;
249 register int c = c1;
250 Lisp_Object overwrite;
251
252 overwrite = current_buffer->overwrite_mode;
253 if (!NILP (Vbefore_change_function) || !NILP (Vafter_change_function)
254 || !NILP (Vbefore_change_functions) || !NILP (Vafter_change_functions))
255 hairy = 1;
256
257 if (!NILP (overwrite)
258 && point < ZV
259 && (EQ (overwrite, Qoverwrite_mode_binary)
260 || (c != '\n' && FETCH_CHAR (point) != '\n'))
261 && (EQ (overwrite, Qoverwrite_mode_binary)
262 || FETCH_CHAR (point) != '\t'
263 || XINT (current_buffer->tab_width) <= 0
264 || XFASTINT (current_buffer->tab_width) > 20
265 || !((current_column () + 1) % XFASTINT (current_buffer->tab_width))))
266 {
267 del_range (point, point + 1);
268 hairy = 2;
269 }
270 if (!NILP (current_buffer->abbrev_mode)
271 && SYNTAX (c) != Sword
272 && NILP (current_buffer->read_only)
273 && point > BEGV && SYNTAX (FETCH_CHAR (point - 1)) == Sword)
274 {
275 int modiff = MODIFF;
276 Fexpand_abbrev ();
277 /* We can't trust the value of Fexpand_abbrev,
278 but if Fexpand_abbrev changed the buffer,
279 assume it expanded something. */
280 if (MODIFF != modiff)
281 hairy = 2;
282 }
283 if ((c == ' ' || c == '\n')
284 && !noautofill
285 && !NILP (current_buffer->auto_fill_function))
286 {
287 insert_and_inherit (&c1, 1);
288 if (c1 == '\n')
289 /* After inserting a newline, move to previous line and fill */
290 /* that. Must have the newline in place already so filling and */
291 /* justification, if any, know where the end is going to be. */
292 SET_PT (point - 1);
293 call0 (current_buffer->auto_fill_function);
294 if (c1 == '\n')
295 SET_PT (point + 1);
296 hairy = 2;
297 }
298 else
299 insert_and_inherit (&c1, 1);
300
301 #ifdef HAVE_FACES
302 /* If previous command specified a face to use, use it. */
303 if (!NILP (Vself_insert_face)
304 && EQ (last_command, Vself_insert_face_command))
305 {
306 Lisp_Object before, after;
307 XSETINT (before, PT - 1);
308 XSETINT (after, PT);
309 Fput_text_property (before, after, Qface, Vself_insert_face, Qnil);
310 Vself_insert_face = Qnil;
311 }
312 #endif
313 synt = SYNTAX (c);
314 if ((synt == Sclose || synt == Smath)
315 && !NILP (Vblink_paren_function) && INTERACTIVE)
316 {
317 call0 (Vblink_paren_function);
318 hairy = 2;
319 }
320 return hairy;
321 }
322 \f
323 /* module initialization */
324
325 syms_of_cmds ()
326 {
327 Qkill_backward_chars = intern ("kill-backward-chars");
328 staticpro (&Qkill_backward_chars);
329
330 Qkill_forward_chars = intern ("kill-forward-chars");
331 staticpro (&Qkill_forward_chars);
332
333 Qoverwrite_mode_binary = intern ("overwrite-mode-binary");
334 staticpro (&Qoverwrite_mode_binary);
335
336 DEFVAR_LISP ("self-insert-face", &Vself_insert_face,
337 "If non-nil, set the face of the next self-inserting character to this.\n\
338 See also `self-insert-face-command'.");
339 Vself_insert_face = Qnil;
340
341 DEFVAR_LISP ("self-insert-face-command", &Vself_insert_face_command,
342 "This is the command that set up `self-insert-face'.\n\
343 If `last-command' does not equal this value, we ignore `self-insert-face'.");
344 Vself_insert_face_command = Qnil;
345
346 DEFVAR_LISP ("blink-paren-function", &Vblink_paren_function,
347 "Function called, if non-nil, whenever a close parenthesis is inserted.\n\
348 More precisely, a char with closeparen syntax is self-inserted.");
349 Vblink_paren_function = Qnil;
350
351 defsubr (&Sforward_char);
352 defsubr (&Sbackward_char);
353 defsubr (&Sforward_line);
354 defsubr (&Sbeginning_of_line);
355 defsubr (&Send_of_line);
356
357 defsubr (&Sdelete_char);
358 defsubr (&Sdelete_backward_char);
359
360 defsubr (&Sself_insert_command);
361 }
362
363 keys_of_cmds ()
364 {
365 int n;
366
367 initial_define_key (global_map, Ctl ('I'), "self-insert-command");
368 for (n = 040; n < 0177; n++)
369 initial_define_key (global_map, n, "self-insert-command");
370 #ifdef MSDOS
371 for (n = 0200; n < 0240; n++)
372 initial_define_key (global_map, n, "self-insert-command");
373 #endif
374 for (n = 0240; n < 0400; n++)
375 initial_define_key (global_map, n, "self-insert-command");
376
377 initial_define_key (global_map, Ctl ('A'), "beginning-of-line");
378 initial_define_key (global_map, Ctl ('B'), "backward-char");
379 initial_define_key (global_map, Ctl ('D'), "delete-char");
380 initial_define_key (global_map, Ctl ('E'), "end-of-line");
381 initial_define_key (global_map, Ctl ('F'), "forward-char");
382 initial_define_key (global_map, 0177, "delete-backward-char");
383 }