aboutsummaryrefslogtreecommitdiffstats
path: root/src/undo.c
diff options
context:
space:
mode:
authorAaron S. Hawley2013-01-08 14:13:31 -0500
committerStefan Monnier2013-01-08 14:13:31 -0500
commit3bace969f386056cedeaba7ac3661167d6d60190 (patch)
treed4dddc07a157d2f2be055c1d0a879d23d292de68 /src/undo.c
parent1c851e98b60d08404e5138b67ccf5b9d72fb4e47 (diff)
downloademacs-3bace969f386056cedeaba7ac3661167d6d60190.tar.gz
emacs-3bace969f386056cedeaba7ac3661167d6d60190.zip
* lisp/simple.el (primitive-undo): Move from undo.c.
* src/undo.c (Fprimitive_undo): Move to simple.el. (syms_of_undo): Remove declaration for Sprimitive_undo. * test/automated/undo-tests.el: New file.
Diffstat (limited to 'src/undo.c')
-rw-r--r--src/undo.c212
1 files changed, 0 insertions, 212 deletions
diff --git a/src/undo.c b/src/undo.c
index 2626fd4ccfe..63edc8e9b8d 100644
--- a/src/undo.c
+++ b/src/undo.c
@@ -452,217 +452,6 @@ user_error (const char *msg)
452} 452}
453 453
454 454
455DEFUN ("primitive-undo", Fprimitive_undo, Sprimitive_undo, 2, 2, 0,
456 doc: /* Undo N records from the front of the list LIST.
457Return what remains of the list. */)
458 (Lisp_Object n, Lisp_Object list)
459{
460 struct gcpro gcpro1, gcpro2;
461 Lisp_Object next;
462 ptrdiff_t count = SPECPDL_INDEX ();
463 register EMACS_INT arg;
464 Lisp_Object oldlist;
465 int did_apply = 0;
466
467#if 0 /* This is a good feature, but would make undo-start
468 unable to do what is expected. */
469 Lisp_Object tem;
470
471 /* If the head of the list is a boundary, it is the boundary
472 preceding this command. Get rid of it and don't count it. */
473 tem = Fcar (list);
474 if (NILP (tem))
475 list = Fcdr (list);
476#endif
477
478 CHECK_NUMBER (n);
479 arg = XINT (n);
480 next = Qnil;
481 GCPRO2 (next, list);
482 /* I don't think we need to gcpro oldlist, as we use it only
483 to check for EQ. ++kfs */
484
485 /* In a writable buffer, enable undoing read-only text that is so
486 because of text properties. */
487 if (NILP (BVAR (current_buffer, read_only)))
488 specbind (Qinhibit_read_only, Qt);
489
490 /* Don't let `intangible' properties interfere with undo. */
491 specbind (Qinhibit_point_motion_hooks, Qt);
492
493 oldlist = BVAR (current_buffer, undo_list);
494
495 while (arg > 0)
496 {
497 while (CONSP (list))
498 {
499 next = XCAR (list);
500 list = XCDR (list);
501 /* Exit inner loop at undo boundary. */
502 if (NILP (next))
503 break;
504 /* Handle an integer by setting point to that value. */
505 if (INTEGERP (next))
506 SET_PT (clip_to_bounds (BEGV, XINT (next), ZV));
507 else if (CONSP (next))
508 {
509 Lisp_Object car, cdr;
510
511 car = XCAR (next);
512 cdr = XCDR (next);
513 if (EQ (car, Qt))
514 {
515 /* Element (t . TIME) records previous modtime.
516 Preserve any flag of NONEXISTENT_MODTIME_NSECS or
517 UNKNOWN_MODTIME_NSECS. */
518 struct buffer *base_buffer = current_buffer;
519 EMACS_TIME mod_time;
520
521 if (CONSP (cdr)
522 && CONSP (XCDR (cdr))
523 && CONSP (XCDR (XCDR (cdr)))
524 && CONSP (XCDR (XCDR (XCDR (cdr))))
525 && INTEGERP (XCAR (XCDR (XCDR (XCDR (cdr)))))
526 && XINT (XCAR (XCDR (XCDR (XCDR (cdr))))) < 0)
527 mod_time =
528 (make_emacs_time
529 (0, XINT (XCAR (XCDR (XCDR (XCDR (cdr))))) / 1000));
530 else
531 mod_time = lisp_time_argument (cdr);
532
533 if (current_buffer->base_buffer)
534 base_buffer = current_buffer->base_buffer;
535
536 /* If this records an obsolete save
537 (not matching the actual disk file)
538 then don't mark unmodified. */
539 if (EMACS_TIME_NE (mod_time, base_buffer->modtime))
540 continue;
541#ifdef CLASH_DETECTION
542 Funlock_buffer ();
543#endif /* CLASH_DETECTION */
544 Fset_buffer_modified_p (Qnil);
545 }
546 else if (EQ (car, Qnil))
547 {
548 /* Element (nil PROP VAL BEG . END) is property change. */
549 Lisp_Object beg, end, prop, val;
550
551 prop = Fcar (cdr);
552 cdr = Fcdr (cdr);
553 val = Fcar (cdr);
554 cdr = Fcdr (cdr);
555 beg = Fcar (cdr);
556 end = Fcdr (cdr);
557
558 if (XINT (beg) < BEGV || XINT (end) > ZV)
559 user_error ("Changes to be undone are outside visible portion of buffer");
560 Fput_text_property (beg, end, prop, val, Qnil);
561 }
562 else if (INTEGERP (car) && INTEGERP (cdr))
563 {
564 /* Element (BEG . END) means range was inserted. */
565
566 if (XINT (car) < BEGV
567 || XINT (cdr) > ZV)
568 user_error ("Changes to be undone are outside visible portion of buffer");
569 /* Set point first thing, so that undoing this undo
570 does not send point back to where it is now. */
571 Fgoto_char (car);
572 Fdelete_region (car, cdr);
573 }
574 else if (EQ (car, Qapply))
575 {
576 /* Element (apply FUN . ARGS) means call FUN to undo. */
577 struct buffer *save_buffer = current_buffer;
578
579 car = Fcar (cdr);
580 cdr = Fcdr (cdr);
581 if (INTEGERP (car))
582 {
583 /* Long format: (apply DELTA START END FUN . ARGS). */
584 Lisp_Object delta = car;
585 Lisp_Object start = Fcar (cdr);
586 Lisp_Object end = Fcar (Fcdr (cdr));
587 Lisp_Object start_mark = Fcopy_marker (start, Qnil);
588 Lisp_Object end_mark = Fcopy_marker (end, Qt);
589
590 cdr = Fcdr (Fcdr (cdr));
591 apply1 (Fcar (cdr), Fcdr (cdr));
592
593 /* Check that the function did what the entry said it
594 would do. */
595 if (!EQ (start, Fmarker_position (start_mark))
596 || (XINT (delta) + XINT (end)
597 != marker_position (end_mark)))
598 error ("Changes to be undone by function different than announced");
599 Fset_marker (start_mark, Qnil, Qnil);
600 Fset_marker (end_mark, Qnil, Qnil);
601 }
602 else
603 apply1 (car, cdr);
604
605 if (save_buffer != current_buffer)
606 error ("Undo function switched buffer");
607 did_apply = 1;
608 }
609 else if (STRINGP (car) && INTEGERP (cdr))
610 {
611 /* Element (STRING . POS) means STRING was deleted. */
612 Lisp_Object membuf;
613 EMACS_INT pos = XINT (cdr);
614
615 membuf = car;
616 if (pos < 0)
617 {
618 if (-pos < BEGV || -pos > ZV)
619 user_error ("Changes to be undone are outside visible portion of buffer");
620 SET_PT (-pos);
621 Finsert (1, &membuf);
622 }
623 else
624 {
625 if (pos < BEGV || pos > ZV)
626 user_error ("Changes to be undone are outside visible portion of buffer");
627 SET_PT (pos);
628
629 /* Now that we record marker adjustments
630 (caused by deletion) for undo,
631 we should always insert after markers,
632 so that undoing the marker adjustments
633 put the markers back in the right place. */
634 Finsert (1, &membuf);
635 SET_PT (pos);
636 }
637 }
638 else if (MARKERP (car) && INTEGERP (cdr))
639 {
640 /* (MARKER . INTEGER) means a marker MARKER
641 was adjusted by INTEGER. */
642 if (XMARKER (car)->buffer)
643 Fset_marker (car,
644 make_number (marker_position (car) - XINT (cdr)),
645 Fmarker_buffer (car));
646 }
647 }
648 }
649 arg--;
650 }
651
652
653 /* Make sure an apply entry produces at least one undo entry,
654 so the test in `undo' for continuing an undo series
655 will work right. */
656 if (did_apply
657 && EQ (oldlist, BVAR (current_buffer, undo_list)))
658 bset_undo_list
659 (current_buffer,
660 Fcons (list3 (Qapply, Qcdr, Qnil), BVAR (current_buffer, undo_list)));
661
662 UNGCPRO;
663 return unbind_to (count, list);
664}
665
666void 455void
667syms_of_undo (void) 456syms_of_undo (void)
668{ 457{
@@ -675,7 +464,6 @@ syms_of_undo (void)
675 last_undo_buffer = NULL; 464 last_undo_buffer = NULL;
676 last_boundary_buffer = NULL; 465 last_boundary_buffer = NULL;
677 466
678 defsubr (&Sprimitive_undo);
679 defsubr (&Sundo_boundary); 467 defsubr (&Sundo_boundary);
680 468
681 DEFVAR_INT ("undo-limit", undo_limit, 469 DEFVAR_INT ("undo-limit", undo_limit,