Mercurial > hg > xemacs-beta
comparison src/indent.c @ 288:e11d67e05968 r21-0b42
Import from CVS: tag r21-0b42
author | cvs |
---|---|
date | Mon, 13 Aug 2007 10:35:54 +0200 |
parents | 6330739388db |
children | 70ad99077275 |
comparison
equal
deleted
inserted
replaced
287:13a0bd77a29d | 288:e11d67e05968 |
---|---|
647 vmotion (struct window *w, Bufpos orig, int vtarget, int *ret_vpos) | 647 vmotion (struct window *w, Bufpos orig, int vtarget, int *ret_vpos) |
648 { | 648 { |
649 return vmotion_1 (w, orig, vtarget, ret_vpos, NULL); | 649 return vmotion_1 (w, orig, vtarget, ret_vpos, NULL); |
650 } | 650 } |
651 | 651 |
652 /* Helper for Fvertical_motion and Fvertical_motion_pixels. | 652 /* Helper for Fvertical_motion. |
653 * Share as much code as possible so these stay synched. | |
654 */ | 653 */ |
655 static | 654 static |
656 Lisp_Object vertical_motion_1 (Lisp_Object lines, Lisp_Object window, | 655 Lisp_Object vertical_motion_1 (Lisp_Object lines, Lisp_Object window, |
657 int pixels) | 656 int pixels) |
658 { | 657 { |
690 w->buffer); | 689 w->buffer); |
691 | 690 |
692 return make_int (value); | 691 return make_int (value); |
693 } | 692 } |
694 | 693 |
695 DEFUN ("vertical-motion", Fvertical_motion, 1, 2, 0, /* | 694 DEFUN ("vertical-motion", Fvertical_motion, 1, 3, 0, /* |
696 Move to start of frame line LINES lines down. | 695 Move to start of frame line LINES lines down. |
697 If LINES is negative, this is moving up. | 696 If LINES is negative, this is moving up. |
698 Optional second argument is WINDOW to move in, | 697 Optional second argument is WINDOW to move in, |
699 the default is the selected window. | 698 the default is the selected window. |
700 | 699 |
701 Sets point to position found; this may be start of line | 700 Sets point to position found; this may be start of line |
702 or just the start of a continuation line. | 701 or just the start of a continuation line. |
703 Returns number of lines moved; may be closer to zero than LINES | 702 If optional third argument PIXELS is nil, returns number |
704 if beginning or end of buffer was reached. | 703 of lines moved; may be closer to zero than LINES if beginning |
704 or end of buffer was reached. If PIXELS is non-nil, the | |
705 vertical pixel height of the motion which took place is | |
706 returned instead of the actual number of lines moved. A | |
707 motion of zero lines returns the height of the current line. | |
705 | 708 |
706 Note that `vertical-motion' sets WINDOW's buffer's point, not | 709 Note that `vertical-motion' sets WINDOW's buffer's point, not |
707 WINDOW's point. (This differs from FSF Emacs, which buggily always | 710 WINDOW's point. (This differs from FSF Emacs, which buggily always |
708 sets current buffer's point, regardless of WINDOW.) | 711 sets current buffer's point, regardless of WINDOW.) |
709 */ | 712 */ |
710 (lines, window)) | 713 (lines, window, pixels)) |
711 { | 714 { |
712 return vertical_motion_1 (lines, window, /* pixels = */ 0); | 715 return vertical_motion_1 (lines, window, !NILP (pixels)); |
713 } | 716 } |
714 | 717 |
715 DEFUN ("vertical-motion-pixels", Fvertical_motion_pixels, 1, 2, 0, /* | 718 /* |
716 Move to start of frame line LINES lines down. | 719 * Like vmotion() but requested and returned movement is in pixels. |
717 If LINES is negative, this is moving up. | 720 * HOW specifies the stopping condition. Positive means move at least |
721 * PIXELS. Negative means at most. Zero means as close as possible. | |
722 */ | |
723 Bufpos | |
724 vmotion_pixels (Lisp_Object window, Bufpos start, int pixels, int how, | |
725 int *motion) | |
726 { | |
727 struct window *w; | |
728 Bufpos eobuf, bobuf; | |
729 int defheight; | |
730 int needed; | |
731 int line, next; | |
732 int remain, abspix, dirn; | |
733 int elt, nelt; | |
734 int i; | |
735 line_start_cache_dynarr *cache; | |
736 int previous = -1; | |
737 int lines; | |
738 | |
739 if (NILP (window)) | |
740 window = Fselected_window (Qnil); | |
741 | |
742 CHECK_WINDOW (window); | |
743 w = XWINDOW (window); | |
744 | |
745 eobuf = BUF_ZV (XBUFFER (w->buffer)); | |
746 bobuf = BUF_BEGV (XBUFFER (w->buffer)); | |
747 | |
748 default_face_height_and_width (window, &defheight, NULL); | |
749 | |
750 /* guess num lines needed in line start cache + a few extra */ | |
751 abspix = abs (pixels); | |
752 needed = (abspix + defheight-1)/defheight + 3; | |
753 | |
754 dirn = (pixels >= 0) ? 1 : -1; | |
755 | |
756 while (1) | |
757 { | |
758 elt = point_in_line_start_cache (w, start, needed); | |
759 assert (elt >= 0); /* in the cache */ | |
760 | |
761 cache = w->line_start_cache; | |
762 nelt = Dynarr_length (cache); | |
763 | |
764 *motion = 0; | |
765 | |
766 if (pixels == 0) | |
767 /* No vertical motion requested so we just return the position | |
768 of the beginning of the current display line. */ | |
769 return Dynarr_atp (cache, elt)->start; | |
770 | |
771 if ((dirn < 0 && elt == 0 && | |
772 Dynarr_atp (cache, elt)->start <= bobuf) || | |
773 (dirn > 0 && elt == nelt-1 && | |
774 Dynarr_atp (cache, elt)->end >= eobuf)) | |
775 return Dynarr_atp (cache, elt)->start; | |
776 | |
777 remain = abspix; | |
778 for (i = elt; (dirn > 0) ? (i < nelt) : (i > 0); i += dirn) | |
779 { | |
780 /* cache line we're considering moving over */ | |
781 int ii = (dirn > 0) ? i : i-1; | |
782 | |
783 if (remain < 0) | |
784 return Dynarr_atp (cache, i)->start; | |
785 | |
786 line = Dynarr_atp (cache, ii)->height; | |
787 next = remain - line; | |
788 | |
789 /* is stopping condition satisfied? */ | |
790 if ((how > 0 && remain <= 0) || /* at least */ | |
791 (how < 0 && next < 0) || /* at most */ | |
792 (how == 0 && remain <= abs (next))) /* closest */ | |
793 return Dynarr_atp (cache, i)->start; | |
794 | |
795 /* moving down and nowhere left to go? */ | |
796 if (dirn > 0 && Dynarr_atp (cache, ii)->end >= eobuf) | |
797 return Dynarr_atp (cache, ii)->start; | |
798 | |
799 /* take the step */ | |
800 remain = next; | |
801 *motion += dirn * line; | |
802 | |
803 /* moving up and nowhere left to go? */ | |
804 if (dirn < 0 && Dynarr_atp (cache, ii)->start <= bobuf) | |
805 return Dynarr_atp (cache, ii)->start; | |
806 } | |
807 | |
808 /* get here => need more cache lines. try again. */ | |
809 assert (abs (*motion) > previous); /* progress? */ | |
810 previous = abs (*motion); | |
811 | |
812 lines = (pixels < 0) ? elt : (nelt - elt); | |
813 needed += (remain*lines + abspix-1)/abspix + 3; | |
814 } | |
815 | |
816 RETURN_NOT_REACHED(0) /* shut up compiler */ | |
817 } | |
818 | |
819 DEFUN ("vertical-motion-pixels", Fvertical_motion_pixels, 1, 3, 0, /* | |
820 Move to start of frame line PIXELS vertical pixels down. | |
821 If PIXELS is negative, this is moving up. | |
822 The actual vertical motion in pixels is returned. | |
823 | |
718 Optional second argument is WINDOW to move in, | 824 Optional second argument is WINDOW to move in, |
719 the default is the selected window. | 825 the default is the selected window. |
720 | 826 |
721 This function is identical in behavior to `vertical-motion' | 827 Optional third argument HOW specifies when to stop. A value |
722 except that the vertical pixel height of the motion which | 828 less than zero indicates that the motion should be no more |
723 took place is returned instead of the actual number of lines | 829 than PIXELS. A value greater than zero indicates that the |
724 moved. A motion of zero lines returns the height of the | 830 motion should be at least PIXELS. Any other value indicates |
725 current line. | 831 that the motion should be as close as possible to PIXELS. |
726 */ | 832 */ |
727 (lines, window)) | 833 (pixels, window, how)) |
728 { | 834 { |
729 return vertical_motion_1 (lines, window, /* pixels = */ 1); | 835 Bufpos bufpos; |
836 Bufpos orig; | |
837 int selected; | |
838 int motion; | |
839 int howto; | |
840 struct window *w; | |
841 | |
842 if (NILP (window)) | |
843 window = Fselected_window (Qnil); | |
844 | |
845 CHECK_WINDOW (window); | |
846 CHECK_INT (pixels); | |
847 | |
848 selected = (EQ (window, Fselected_window (Qnil))); | |
849 | |
850 w = XWINDOW (window); | |
851 | |
852 orig = selected ? BUF_PT (XBUFFER (w->buffer)) | |
853 : marker_position (w->pointm[CURRENT_DISP]); | |
854 | |
855 howto = INTP (how) ? XINT (how) : 0; | |
856 | |
857 bufpos = vmotion_pixels (window, orig, XINT (pixels), howto, &motion); | |
858 | |
859 if (selected) | |
860 BUF_SET_PT (XBUFFER (w->buffer), bufpos); | |
861 else | |
862 set_marker_restricted (w->pointm[CURRENT_DISP], | |
863 make_int(bufpos), | |
864 w->buffer); | |
865 | |
866 return make_int (motion); | |
730 } | 867 } |
731 | 868 |
732 | 869 |
733 void | 870 void |
734 syms_of_indent (void) | 871 syms_of_indent (void) |