comparison src/cmds.c @ 0:376386a54a3c r19-14

Import from CVS: tag r19-14
author cvs
date Mon, 13 Aug 2007 08:45:50 +0200
parents
children 27bc7f280385
comparison
equal deleted inserted replaced
-1:000000000000 0:376386a54a3c
1 /* Simple built-in editing commands.
2 Copyright (C) 1985, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
3
4 This file is part of XEmacs.
5
6 XEmacs is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
9 later version.
10
11 XEmacs is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with XEmacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
20
21 /* Synched up with: Mule 2.0, FSF 19.30. */
22
23 #include <config.h>
24 #include "lisp.h"
25 #include "commands.h"
26 #include "buffer.h"
27 #include "syntax.h"
28 #include "insdel.h"
29
30 Lisp_Object Qkill_forward_chars;
31 Lisp_Object Qself_insert_command;
32
33 Lisp_Object Vblink_paren_function;
34
35 /* A possible value for a buffer's overwrite-mode variable. */
36 Lisp_Object Qoverwrite_mode_binary;
37
38 /* Non-nil means put this face on the next self-inserting character. */
39 Lisp_Object Vself_insert_face;
40
41 /* This is the command that set up Vself_insert_face. */
42 Lisp_Object Vself_insert_face_command;
43
44
45 DEFUN ("forward-char", Fforward_char, Sforward_char, 0, 2, "_p" /*
46 Move point right ARG characters (left if ARG negative).
47 On reaching end of buffer, stop and signal error.
48 If BUFFER is nil, the current buffer is assumed.
49 */ )
50 (arg, buffer)
51 Lisp_Object arg, buffer;
52 {
53 struct buffer *buf = decode_buffer (buffer, 1);
54
55 if (NILP (arg))
56 arg = make_int (1);
57 else
58 CHECK_INT (arg);
59
60 /* This used to just set point to point + XINT (arg), and then check
61 to see if it was within boundaries. But now that SET_PT can
62 potentially do a lot of stuff (calling entering and exiting
63 hooks, etcetera), that's not a good approach. So we validate the
64 proposed position, then set point. */
65 {
66 Bufpos new_point = BUF_PT (buf) + XINT (arg);
67
68 if (new_point < BUF_BEGV (buf))
69 {
70 BUF_SET_PT (buf, BUF_BEGV (buf));
71 Fsignal (Qbeginning_of_buffer, Qnil);
72 }
73 if (new_point > BUF_ZV (buf))
74 {
75 BUF_SET_PT (buf, BUF_ZV (buf));
76 Fsignal (Qend_of_buffer, Qnil);
77 }
78
79 BUF_SET_PT (buf, new_point);
80 }
81
82 return Qnil;
83 }
84
85 DEFUN ("backward-char", Fbackward_char, Sbackward_char, 0, 2, "_p" /*
86 Move point left ARG characters (right if ARG negative).
87 On attempt to pass beginning or end of buffer, stop and signal error.
88 If BUFFER is nil, the current buffer is assumed.
89 */ )
90 (arg, buffer)
91 Lisp_Object arg, buffer;
92 {
93 if (NILP (arg))
94 arg = make_int (1);
95 else
96 CHECK_INT (arg);
97
98 XSETINT (arg, - XINT (arg));
99 return Fforward_char (arg, buffer);
100 }
101
102 DEFUN ("forward-line", Fforward_line, Sforward_line, 0, 2, "_p" /*
103 Move ARG lines forward (backward if ARG is negative).
104 Precisely, if point is on line I, move to the start of line I + ARG.
105 If there isn't room, go as far as possible (no error).
106 Returns the count of lines left to move. If moving forward,
107 that is ARG - number of lines moved; if backward, ARG + number moved.
108 With positive ARG, a non-empty line at the end counts as one line
109 successfully moved (for the return value).
110 If BUFFER is nil, the current buffer is assumed.
111 */ )
112 (arg, buffer)
113 Lisp_Object arg, buffer;
114 {
115 struct buffer *buf = decode_buffer (buffer, 1);
116 Bufpos pos2 = BUF_PT (buf);
117 Bufpos pos;
118 int count, shortage, negp;
119
120 if (NILP (arg))
121 count = 1;
122 else
123 {
124 CHECK_INT (arg);
125 count = XINT (arg);
126 }
127
128 negp = count <= 0;
129 pos = scan_buffer (buf, '\n', pos2, 0, count - negp, &shortage, 1);
130 if (shortage > 0
131 && (negp
132 || (BUF_ZV (buf) > BUF_BEGV (buf)
133 && pos != pos2
134 && BUF_FETCH_CHAR (buf, pos - 1) != '\n')))
135 shortage--;
136 BUF_SET_PT (buf, pos);
137 return make_int (negp ? - shortage : shortage);
138 }
139
140 DEFUN ("beginning-of-line", Fbeginning_of_line, Sbeginning_of_line,
141 0, 2, "_p" /*
142 Move point to beginning of current line.
143 With argument ARG not nil or 1, move forward ARG - 1 lines first.
144 If scan reaches end of buffer, stop there without error.
145 If BUFFER is nil, the current buffer is assumed.
146 */ )
147 (arg, buffer)
148 Lisp_Object arg, buffer;
149 {
150 struct buffer *b = decode_buffer (buffer, 1);
151
152 XSETBUFFER (buffer, b);
153 if (NILP (arg))
154 arg = make_int (1);
155 else
156 CHECK_INT (arg);
157
158 Fforward_line (make_int (XINT (arg) - 1), buffer);
159 return Qnil;
160 }
161
162 DEFUN ("end-of-line", Fend_of_line, Send_of_line,
163 0, 2, "_p" /*
164 Move point to end of current line.
165 With argument ARG not nil or 1, move forward ARG - 1 lines first.
166 If scan reaches end of buffer, stop there without error.
167 If BUFFER is nil, the current buffer is assumed.
168 */ )
169 (arg, buffer)
170 Lisp_Object arg, buffer;
171 {
172 struct buffer *buf = decode_buffer (buffer, 1);
173
174 XSETBUFFER (buffer, buf);
175
176 if (NILP (arg))
177 arg = make_int (1);
178 else
179 CHECK_INT (arg);
180
181 BUF_SET_PT (buf, find_before_next_newline (buf, BUF_PT (buf), 0,
182 XINT (arg) - (XINT (arg) <= 0)));
183 return Qnil;
184 }
185
186 DEFUN ("delete-char", Fdelete_char, Sdelete_char, 1, 2, "*p\nP" /*
187 Delete the following ARG characters (previous, with negative arg).
188 Optional second arg KILLFLAG non-nil means kill instead (save in kill ring).
189 Interactively, ARG is the prefix arg, and KILLFLAG is set if
190 ARG was explicitly specified.
191 */ )
192 (arg, killflag)
193 Lisp_Object arg, killflag;
194 {
195 /* This function can GC */
196 Bufpos pos;
197 struct buffer *buf = current_buffer;
198
199 CHECK_INT (arg);
200
201 pos = BUF_PT (buf) + XINT (arg);
202 if (NILP (killflag))
203 {
204 if (XINT (arg) < 0)
205 {
206 if (pos < BUF_BEGV (buf))
207 signal_error (Qbeginning_of_buffer, Qnil);
208 else
209 buffer_delete_range (buf, pos, BUF_PT (buf), 0);
210 }
211 else
212 {
213 if (pos > BUF_ZV (buf))
214 signal_error (Qend_of_buffer, Qnil);
215 else
216 buffer_delete_range (buf, BUF_PT (buf), pos, 0);
217 }
218 }
219 else
220 {
221 call1 (Qkill_forward_chars, arg);
222 }
223 return Qnil;
224 }
225
226 DEFUN ("delete-backward-char", Fdelete_backward_char, Sdelete_backward_char,
227 1, 2, "*p\nP" /*
228 Delete the previous ARG characters (following, with negative ARG).
229 Optional second arg KILLFLAG non-nil means kill instead (save in kill ring).
230 Interactively, ARG is the prefix arg, and KILLFLAG is set if
231 ARG was explicitly specified.
232 */ )
233 (arg, killflag)
234 Lisp_Object arg, killflag;
235 {
236 /* This function can GC */
237 CHECK_INT (arg);
238 return Fdelete_char (make_int (-XINT (arg)), killflag);
239 }
240
241 static void internal_self_insert (Emchar ch, int noautofill);
242
243 DEFUN ("self-insert-command", Fself_insert_command, Sself_insert_command, 1, 1, "*p" /*
244 Insert the character you type.
245 Whichever character you type to run this command is inserted.
246 */ )
247 (arg)
248 Lisp_Object arg;
249 {
250 /* This function can GC */
251 int n;
252 Emchar ch;
253 Lisp_Object c;
254 CHECK_INT (arg);
255
256 if (CHAR_OR_CHAR_INTP (Vlast_command_char))
257 c = Vlast_command_char;
258 else
259 c = Fevent_to_character (Vlast_command_event, Qnil, Qnil, Qt);
260
261 if (NILP (c))
262 signal_simple_error ("last typed character has no ASCII equivalent",
263 Fcopy_event (Vlast_command_event, Qnil));
264
265 CHECK_CHAR_COERCE_INT (c);
266
267 n = XINT (arg);
268 ch = XCHAR (c);
269 #if 0 /* FSFmacs */
270 /* #### This optimization won't work because of differences in
271 how the start-open and end-open properties default for text
272 properties. See internal_self_insert(). */
273 if (n >= 2 && NILP (current_buffer->overwrite_mode))
274 {
275 n -= 2;
276 /* The first one might want to expand an abbrev. */
277 internal_self_insert (c, 1);
278 /* The bulk of the copies of this char can be inserted simply.
279 We don't have to handle a user-specified face specially
280 because it will get inherited from the first char inserted. */
281 Finsert_char (make_char (c), make_int (n), Qt, Qnil);
282 /* The last one might want to auto-fill. */
283 internal_self_insert (c, 0);
284 }
285 else
286 #endif /* 0 */
287 while (n > 0)
288 {
289 n--;
290 internal_self_insert (ch, (n != 0));
291 }
292 return Qnil;
293 }
294
295 /* Insert character C1. If NOAUTOFILL is nonzero, don't do autofill
296 even if it is enabled.
297
298 FSF:
299
300 If this insertion is suitable for direct output (completely simple),
301 return 0. A value of 1 indicates this *might* not have been simple.
302 A value of 2 means this did things that call for an undo boundary. */
303
304 static void
305 internal_self_insert (Emchar c1, int noautofill)
306 {
307 /* This function can GC */
308 /* int hairy = 0; -- unused */
309 REGISTER enum syntaxcode synt;
310 REGISTER Emchar c2;
311 Lisp_Object overwrite;
312 Lisp_Object syntax_table;
313 struct buffer *buf = current_buffer;
314
315 overwrite = buf->overwrite_mode;
316 syntax_table = buf->syntax_table;
317
318 #if 0
319 /* No, this is very bad, it makes undo *always* undo a character at a time
320 instead of grouping consecutive self-inserts together. Nasty nasty.
321 */
322 if (!NILP (Vbefore_change_functions) || !NILP (Vafter_change_functions)
323 || !NILP (Vbefore_change_function) || !NILP (Vafter_change_function))
324 hairy = 1;
325 #endif
326
327 if (!NILP (overwrite)
328 && BUF_PT (buf) < BUF_ZV (buf)
329 && (EQ (overwrite, Qoverwrite_mode_binary)
330 || (c1 != '\n' && BUF_FETCH_CHAR (buf, BUF_PT (buf)) != '\n'))
331 && (EQ (overwrite, Qoverwrite_mode_binary)
332 || BUF_FETCH_CHAR (buf, BUF_PT (buf)) != '\t'
333 || XINT (buf->tab_width) <= 0
334 || XINT (buf->tab_width) > 20
335 || !((current_column (buf) + 1) % XINT (buf->tab_width))))
336 {
337 buffer_delete_range (buf, BUF_PT (buf), BUF_PT (buf) + 1, 0);
338 /* hairy = 2; */
339 }
340
341 if (!NILP (buf->abbrev_mode)
342 && !WORD_SYNTAX_P (syntax_table, c1)
343 && NILP (buf->read_only)
344 && BUF_PT (buf) > BUF_BEGV (buf))
345 {
346 c2 = BUF_FETCH_CHAR (buf, BUF_PT (buf) - 1);
347
348 if (WORD_SYNTAX_P (syntax_table, c2))
349 {
350 /* int modiff = BUF_MODIFF (current_buffer); */
351 Fexpand_abbrev ();
352 /* We can't trust the value of Fexpand_abbrev,
353 but if Fexpand_abbrev changed the buffer,
354 assume it expanded something. */
355 /* if (BUF_MODIFF (buf) != modiff)
356 hairy = 2; */
357 }
358 }
359 if ((c1 == ' ' || c1 == '\n')
360 && !noautofill
361 && !NILP (buf->auto_fill_function))
362 {
363 buffer_insert_emacs_char (buf, c1);
364 if (c1 == '\n')
365 /* After inserting a newline, move to previous line and fill */
366 /* that. Must have the newline in place already so filling and */
367 /* justification, if any, know where the end is going to be. */
368 BUF_SET_PT (buf, BUF_PT (buf) - 1);
369 call0 (buf->auto_fill_function);
370 if (c1 == '\n')
371 BUF_SET_PT (buf, BUF_PT (buf) + 1);
372 /* hairy = 2; */
373 }
374 else
375 buffer_insert_emacs_char (buf, c1);
376
377 /* If previous command specified a face to use, use it. */
378 if (!NILP (Vself_insert_face)
379 && EQ (Vlast_command, Vself_insert_face_command))
380 {
381 Lisp_Object before, after;
382 XSETINT (before, BUF_PT (buf) - 1);
383 XSETINT (after, BUF_PT (buf));
384 Fput_text_property (before, after, Qface, Vself_insert_face, Qnil);
385 Fput_text_property (before, after, Qstart_open, Qt, Qnil);
386 Fput_text_property (before, after, Qend_open, Qnil, Qnil);
387 /* #### FSFmacs properties are normally closed ("sticky") on the
388 end but not the beginning. It's the opposite for us. */
389 Vself_insert_face = Qnil;
390 }
391 synt = SYNTAX (syntax_table, c1);
392 if ((synt == Sclose || synt == Smath)
393 && !NILP (Vblink_paren_function) && INTERACTIVE
394 && !noautofill)
395 {
396 call0 (Vblink_paren_function);
397 /* hairy = 2; */
398 }
399
400 /* return hairy; */
401 }
402
403 /* (this comes from Mule but is a generally good idea) */
404
405 DEFUN ("self-insert-internal", Fself_insert_internal, Sself_insert_internal,
406 1, 1, 0 /*
407 Invoke `self-insert-command' as if CH is entered from keyboard.
408 */ )
409 (ch)
410 Lisp_Object ch;
411 {
412 /* This function can GC */
413 CHECK_CHAR_COERCE_INT (ch);
414 internal_self_insert (XCHAR (ch), 0);
415 return Qnil;
416 }
417
418 /* module initialization */
419
420 void
421 syms_of_cmds (void)
422 {
423 defsymbol (&Qkill_forward_chars, "kill-forward-chars");
424 defsymbol (&Qself_insert_command, "self-insert-command");
425 defsymbol (&Qoverwrite_mode_binary, "overwrite-mode-binary");
426
427 defsubr (&Sforward_char);
428 defsubr (&Sbackward_char);
429 defsubr (&Sforward_line);
430 defsubr (&Sbeginning_of_line);
431 defsubr (&Send_of_line);
432
433 defsubr (&Sdelete_char);
434 defsubr (&Sdelete_backward_char);
435
436 defsubr (&Sself_insert_command);
437 defsubr (&Sself_insert_internal);
438 }
439
440 void
441 vars_of_cmds (void)
442 {
443 DEFVAR_LISP ("self-insert-face", &Vself_insert_face /*
444 If non-nil, set the face of the next self-inserting character to this.
445 See also `self-insert-face-command'.
446 */ );
447 Vself_insert_face = Qnil;
448
449 DEFVAR_LISP ("self-insert-face-command", &Vself_insert_face_command /*
450 This is the command that set up `self-insert-face'.
451 If `last-command' does not equal this value, we ignore `self-insert-face'.
452 */ );
453 Vself_insert_face_command = Qnil;
454
455 DEFVAR_LISP ("blink-paren-function", &Vblink_paren_function /*
456 Function called, if non-nil, whenever a close parenthesis is inserted.
457 More precisely, a char with closeparen syntax is self-inserted.
458 */ );
459 Vblink_paren_function = Qnil;
460 }