Mercurial > emacs
comparison src/cmds.c @ 111570:ffe2002d45c4
merge trunk
author | Kenichi Handa <handa@m17n.org> |
---|---|
date | Wed, 08 Sep 2010 12:55:57 +0900 |
parents | 8102180db0fb |
children | 01aabf6189ef |
comparison
equal
deleted
inserted
replaced
111569:0187fc875872 | 111570:ffe2002d45c4 |
---|---|
30 #include "keyboard.h" | 30 #include "keyboard.h" |
31 #include "keymap.h" | 31 #include "keymap.h" |
32 #include "dispextern.h" | 32 #include "dispextern.h" |
33 #include "frame.h" | 33 #include "frame.h" |
34 | 34 |
35 Lisp_Object Qkill_forward_chars, Qkill_backward_chars, Vblink_paren_function; | 35 Lisp_Object Qkill_forward_chars, Qkill_backward_chars; |
36 | 36 |
37 /* A possible value for a buffer's overwrite-mode variable. */ | 37 /* A possible value for a buffer's overwrite-mode variable. */ |
38 Lisp_Object Qoverwrite_mode_binary; | 38 Lisp_Object Qoverwrite_mode_binary; |
39 | 39 |
40 static int internal_self_insert (int, int); | 40 static int internal_self_insert (int, int); |
302 if (!CHARACTERP (last_command_event)) | 302 if (!CHARACTERP (last_command_event)) |
303 bitch_at_user (); | 303 bitch_at_user (); |
304 { | 304 { |
305 int character = translate_char (Vtranslation_table_for_input, | 305 int character = translate_char (Vtranslation_table_for_input, |
306 XINT (last_command_event)); | 306 XINT (last_command_event)); |
307 if (XINT (n) >= 2 && NILP (current_buffer->overwrite_mode)) | 307 int val = internal_self_insert (character, XFASTINT (n)); |
308 { | 308 if (val == 2) |
309 XSETFASTINT (n, XFASTINT (n) - 2); | 309 nonundocount = 0; |
310 /* The first one might want to expand an abbrev. */ | 310 frame_make_pointer_invisible (); |
311 internal_self_insert (character, 1); | |
312 /* The bulk of the copies of this char can be inserted simply. | |
313 We don't have to handle a user-specified face specially | |
314 because it will get inherited from the first char inserted. */ | |
315 Finsert_char (make_number (character), n, Qt); | |
316 /* The last one might want to auto-fill. */ | |
317 internal_self_insert (character, 0); | |
318 } | |
319 else | |
320 while (XINT (n) > 0) | |
321 { | |
322 int val; | |
323 /* Ok since old and new vals both nonneg */ | |
324 XSETFASTINT (n, XFASTINT (n) - 1); | |
325 val = internal_self_insert (character, XFASTINT (n) != 0); | |
326 if (val == 2) | |
327 nonundocount = 0; | |
328 frame_make_pointer_invisible (); | |
329 } | |
330 } | 311 } |
331 | 312 |
332 return Qnil; | 313 return Qnil; |
333 } | 314 } |
334 | 315 |
335 /* Insert character C. If NOAUTOFILL is nonzero, don't do autofill | 316 /* Insert N times character C |
336 even if it is enabled. | |
337 | 317 |
338 If this insertion is suitable for direct output (completely simple), | 318 If this insertion is suitable for direct output (completely simple), |
339 return 0. A value of 1 indicates this *might* not have been simple. | 319 return 0. A value of 1 indicates this *might* not have been simple. |
340 A value of 2 means this did things that call for an undo boundary. */ | 320 A value of 2 means this did things that call for an undo boundary. */ |
341 | 321 |
342 static Lisp_Object Qexpand_abbrev; | 322 static Lisp_Object Qexpand_abbrev; |
343 static Lisp_Object Qpost_self_insert_hook, Vpost_self_insert_hook; | 323 static Lisp_Object Qpost_self_insert_hook, Vpost_self_insert_hook; |
344 | 324 |
345 static int | 325 static int |
346 internal_self_insert (int c, int noautofill) | 326 internal_self_insert (int c, int n) |
347 { | 327 { |
348 int hairy = 0; | 328 int hairy = 0; |
349 Lisp_Object tem; | 329 Lisp_Object tem; |
350 register enum syntaxcode synt; | 330 register enum syntaxcode synt; |
351 Lisp_Object overwrite, string; | 331 Lisp_Object overwrite; |
352 /* Length of multi-byte form of C. */ | 332 /* Length of multi-byte form of C. */ |
353 int len; | 333 int len; |
354 /* Working buffer and pointer for multi-byte form of C. */ | 334 /* Working buffer and pointer for multi-byte form of C. */ |
355 unsigned char str[MAX_MULTIBYTE_LENGTH]; | 335 unsigned char str[MAX_MULTIBYTE_LENGTH]; |
356 int chars_to_delete = 0; | 336 int chars_to_delete = 0; |
389 C2 and several characters following C2. */ | 369 C2 and several characters following C2. */ |
390 | 370 |
391 /* This is the character after point. */ | 371 /* This is the character after point. */ |
392 int c2 = FETCH_CHAR (PT_BYTE); | 372 int c2 = FETCH_CHAR (PT_BYTE); |
393 | 373 |
394 /* Column the cursor should be placed at after this insertion. | |
395 The correct value should be calculated only when necessary. */ | |
396 int target_clm = 0; | |
397 | |
398 /* Overwriting in binary-mode always replaces C2 by C. | 374 /* Overwriting in binary-mode always replaces C2 by C. |
399 Overwriting in textual-mode doesn't always do that. | 375 Overwriting in textual-mode doesn't always do that. |
400 It inserts newlines in the usual way, | 376 It inserts newlines in the usual way, |
401 and inserts any character at end of line | 377 and inserts any character at end of line |
402 or before a tab if it doesn't use the whole width of the tab. */ | 378 or before a tab if it doesn't use the whole width of the tab. */ |
403 if (EQ (overwrite, Qoverwrite_mode_binary) | 379 if (EQ (overwrite, Qoverwrite_mode_binary)) |
404 || (c != '\n' | 380 chars_to_delete = n; |
405 && c2 != '\n' | 381 else if (c != '\n' && c2 != '\n') |
406 && ! (c2 == '\t' | |
407 && XINT (current_buffer->tab_width) > 0 | |
408 && XFASTINT (current_buffer->tab_width) < 20 | |
409 && (target_clm = ((int) current_column () /* iftc */ | |
410 + XINT (Fchar_width (make_number (c)))), | |
411 target_clm % XFASTINT (current_buffer->tab_width))))) | |
412 { | 382 { |
413 int pos = PT; | 383 int pos = PT; |
414 int pos_byte = PT_BYTE; | 384 int pos_byte = PT_BYTE; |
415 | 385 /* Column the cursor should be placed at after this insertion. |
416 if (target_clm == 0) | 386 The correct value should be calculated only when necessary. */ |
417 chars_to_delete = 1; | 387 int target_clm = ((int) current_column () /* iftc */ |
418 else | 388 + n * XINT (Fchar_width (make_number (c)))); |
419 { | 389 |
420 /* The actual cursor position after the trial of moving | 390 /* The actual cursor position after the trial of moving |
421 to column TARGET_CLM. It is greater than TARGET_CLM | 391 to column TARGET_CLM. It is greater than TARGET_CLM |
422 if the TARGET_CLM is middle of multi-column | 392 if the TARGET_CLM is middle of multi-column |
423 character. In that case, the new point is set after | 393 character. In that case, the new point is set after |
424 that character. */ | 394 that character. */ |
426 = XFASTINT (Fmove_to_column (make_number (target_clm), Qnil)); | 396 = XFASTINT (Fmove_to_column (make_number (target_clm), Qnil)); |
427 | 397 |
428 chars_to_delete = PT - pos; | 398 chars_to_delete = PT - pos; |
429 | 399 |
430 if (actual_clm > target_clm) | 400 if (actual_clm > target_clm) |
431 { | 401 { /* We will delete too many columns. Let's fill columns |
432 /* We will delete too many columns. Let's fill columns | |
433 by spaces so that the remaining text won't move. */ | 402 by spaces so that the remaining text won't move. */ |
403 EMACS_INT actual = PT_BYTE; | |
404 DEC_POS (actual); | |
405 if (FETCH_CHAR (actual) == '\t') | |
406 /* Rather than add spaces, let's just keep the tab. */ | |
407 chars_to_delete--; | |
408 else | |
434 spaces_to_insert = actual_clm - target_clm; | 409 spaces_to_insert = actual_clm - target_clm; |
435 } | 410 } |
436 } | 411 |
437 SET_PT_BOTH (pos, pos_byte); | 412 SET_PT_BOTH (pos, pos_byte); |
438 hairy = 2; | |
439 } | 413 } |
440 hairy = 2; | 414 hairy = 2; |
441 } | 415 } |
442 | 416 |
443 synt = SYNTAX (c); | 417 synt = SYNTAX (c); |
472 hairy = 2; | 446 hairy = 2; |
473 } | 447 } |
474 | 448 |
475 if (chars_to_delete) | 449 if (chars_to_delete) |
476 { | 450 { |
477 string = make_string_from_bytes (str, 1, len); | 451 int mc = ((NILP (current_buffer->enable_multibyte_characters) |
452 && SINGLE_BYTE_CHAR_P (c)) | |
453 ? UNIBYTE_TO_CHAR (c) : c); | |
454 Lisp_Object string = Fmake_string (make_number (n), make_number (mc)); | |
455 | |
478 if (spaces_to_insert) | 456 if (spaces_to_insert) |
479 { | 457 { |
480 tem = Fmake_string (make_number (spaces_to_insert), | 458 tem = Fmake_string (make_number (spaces_to_insert), |
481 make_number (' ')); | 459 make_number (' ')); |
482 string = concat2 (tem, string); | 460 string = concat2 (string, tem); |
483 } | 461 } |
484 | 462 |
485 replace_range (PT, PT + chars_to_delete, string, 1, 1, 1); | 463 replace_range (PT, PT + chars_to_delete, string, 1, 1, 1); |
486 Fforward_char (make_number (1 + spaces_to_insert)); | 464 Fforward_char (make_number (n + spaces_to_insert)); |
465 } | |
466 else if (n > 1) | |
467 { | |
468 USE_SAFE_ALLOCA; | |
469 unsigned char *strn, *p; | |
470 SAFE_ALLOCA (strn, unsigned char*, n * len); | |
471 for (p = strn; n > 0; n--, p += len) | |
472 memcpy (p, str, len); | |
473 insert_and_inherit (strn, p - strn); | |
474 SAFE_FREE (); | |
487 } | 475 } |
488 else | 476 else |
489 insert_and_inherit (str, len); | 477 insert_and_inherit (str, len); |
490 | 478 |
491 if ((CHAR_TABLE_P (Vauto_fill_chars) | 479 if ((CHAR_TABLE_P (Vauto_fill_chars) |
492 ? !NILP (CHAR_TABLE_REF (Vauto_fill_chars, c)) | 480 ? !NILP (CHAR_TABLE_REF (Vauto_fill_chars, c)) |
493 : (c == ' ' || c == '\n')) | 481 : (c == ' ' || c == '\n')) |
494 && !noautofill | |
495 && !NILP (current_buffer->auto_fill_function)) | 482 && !NILP (current_buffer->auto_fill_function)) |
496 { | 483 { |
497 Lisp_Object tem; | 484 Lisp_Object tem; |
498 | 485 |
499 if (c == '\n') | 486 if (c == '\n') |
507 SET_PT_BOTH (PT + 1, PT_BYTE + 1); | 494 SET_PT_BOTH (PT + 1, PT_BYTE + 1); |
508 if (!NILP (tem)) | 495 if (!NILP (tem)) |
509 hairy = 2; | 496 hairy = 2; |
510 } | 497 } |
511 | 498 |
512 if ((synt == Sclose || synt == Smath) | |
513 && !NILP (Vblink_paren_function) && INTERACTIVE | |
514 && !noautofill) | |
515 { | |
516 call0 (Vblink_paren_function); | |
517 hairy = 2; | |
518 } | |
519 /* Run hooks for electric keys. */ | 499 /* Run hooks for electric keys. */ |
520 call1 (Vrun_hooks, Qpost_self_insert_hook); | 500 call1 (Vrun_hooks, Qpost_self_insert_hook); |
521 | 501 |
522 return hairy; | 502 return hairy; |
523 } | 503 } |
544 | 524 |
545 DEFVAR_LISP ("post-self-insert-hook", &Vpost_self_insert_hook, | 525 DEFVAR_LISP ("post-self-insert-hook", &Vpost_self_insert_hook, |
546 doc: /* Hook run at the end of `self-insert-command'. | 526 doc: /* Hook run at the end of `self-insert-command'. |
547 This run is run after inserting the charater. */); | 527 This run is run after inserting the charater. */); |
548 Vpost_self_insert_hook = Qnil; | 528 Vpost_self_insert_hook = Qnil; |
549 | |
550 DEFVAR_LISP ("blink-paren-function", &Vblink_paren_function, | |
551 doc: /* Function called, if non-nil, whenever a close parenthesis is inserted. | |
552 More precisely, a char with closeparen syntax is self-inserted. */); | |
553 Vblink_paren_function = Qnil; | |
554 | 529 |
555 defsubr (&Sforward_point); | 530 defsubr (&Sforward_point); |
556 defsubr (&Sforward_char); | 531 defsubr (&Sforward_char); |
557 defsubr (&Sbackward_char); | 532 defsubr (&Sbackward_char); |
558 defsubr (&Sforward_line); | 533 defsubr (&Sforward_line); |