diff options
| author | Richard M. Stallman | 2001-12-28 05:15:59 +0000 |
|---|---|---|
| committer | Richard M. Stallman | 2001-12-28 05:15:59 +0000 |
| commit | af894fc98aaec826059cf8e489070862376a4749 (patch) | |
| tree | c4c0f6f6cd9181fd2ce116a289959d5983fa5afb | |
| parent | 1d14d232ddf738ffb019560444536b5a9eedc90c (diff) | |
| download | emacs-af894fc98aaec826059cf8e489070862376a4749.tar.gz emacs-af894fc98aaec826059cf8e489070862376a4749.zip | |
(line-move-invisible): New subroutine.
(line-move-to-column): New subroutine--smarter about advancing over
invisible parts of a line, or lines, but only as long as hpos grows.
(line-move-finish): New subroutine: repeatedly processes desired
column, intangibility, and fields.
(line-move): Use those subroutines.
When moving lines downward, skip invisible text first rather than last.
| -rw-r--r-- | lisp/simple.el | 160 |
1 files changed, 90 insertions, 70 deletions
diff --git a/lisp/simple.el b/lisp/simple.el index 0909090f5b7..8229a8cb4fa 100644 --- a/lisp/simple.el +++ b/lisp/simple.el | |||
| @@ -2530,6 +2530,15 @@ Outline mode sets this." | |||
| 2530 | :type 'boolean | 2530 | :type 'boolean |
| 2531 | :group 'editing-basics) | 2531 | :group 'editing-basics) |
| 2532 | 2532 | ||
| 2533 | (defun line-move-invisible (pos) | ||
| 2534 | "Return non-nil if the character after POS is currently invisible." | ||
| 2535 | (let ((prop | ||
| 2536 | (get-char-property pos 'invisible))) | ||
| 2537 | (if (eq buffer-invisibility-spec t) | ||
| 2538 | prop | ||
| 2539 | (or (memq prop buffer-invisibility-spec) | ||
| 2540 | (assq prop buffer-invisibility-spec))))) | ||
| 2541 | |||
| 2533 | ;; This is the guts of next-line and previous-line. | 2542 | ;; This is the guts of next-line and previous-line. |
| 2534 | ;; Arg says how many lines to move. | 2543 | ;; Arg says how many lines to move. |
| 2535 | (defun line-move (arg) | 2544 | (defun line-move (arg) |
| @@ -2563,89 +2572,100 @@ Outline mode sets this." | |||
| 2563 | (bolp))) | 2572 | (bolp))) |
| 2564 | (signal (if (< arg 0) | 2573 | (signal (if (< arg 0) |
| 2565 | 'beginning-of-buffer | 2574 | 'beginning-of-buffer |
| 2566 | 'end-of-buffer) | 2575 | a 'end-of-buffer) |
| 2567 | nil)) | 2576 | nil)) |
| 2568 | ;; Move by arg lines, but ignore invisible ones. | 2577 | ;; Move by arg lines, but ignore invisible ones. |
| 2569 | (while (> arg 0) | 2578 | (while (> arg 0) |
| 2579 | ;; If the following character is currently invisible, | ||
| 2580 | ;; skip all characters with that same `invisible' property value. | ||
| 2581 | (while (and (not (eobp)) (line-move-invisible (point))) | ||
| 2582 | (goto-char (next-char-property-change (point)))) | ||
| 2583 | ;; Now move a line. | ||
| 2570 | (end-of-line) | 2584 | (end-of-line) |
| 2571 | (and (zerop (vertical-motion 1)) | 2585 | (and (zerop (vertical-motion 1)) |
| 2572 | (signal 'end-of-buffer nil)) | 2586 | (signal 'end-of-buffer nil)) |
| 2573 | ;; If the following character is currently invisible, | ||
| 2574 | ;; skip all characters with that same `invisible' property value. | ||
| 2575 | (while (and (not (eobp)) | ||
| 2576 | (let ((prop | ||
| 2577 | (get-char-property (point) 'invisible))) | ||
| 2578 | (if (eq buffer-invisibility-spec t) | ||
| 2579 | prop | ||
| 2580 | (or (memq prop buffer-invisibility-spec) | ||
| 2581 | (assq prop buffer-invisibility-spec))))) | ||
| 2582 | (if (get-text-property (point) 'invisible) | ||
| 2583 | (goto-char (or (next-single-property-change (point) 'invisible) | ||
| 2584 | (point-max))) | ||
| 2585 | (goto-char (next-overlay-change (point))))) | ||
| 2586 | (setq arg (1- arg))) | 2587 | (setq arg (1- arg))) |
| 2587 | (while (< arg 0) | 2588 | (while (< arg 0) |
| 2588 | (beginning-of-line) | 2589 | (beginning-of-line) |
| 2589 | (and (zerop (vertical-motion -1)) | 2590 | (and (zerop (vertical-motion -1)) |
| 2590 | (signal 'beginning-of-buffer nil)) | 2591 | (signal 'beginning-of-buffer nil)) |
| 2591 | (while (and (not (bobp)) | 2592 | (setq arg (1+ arg)) |
| 2592 | (let ((prop | 2593 | (while (and (not (bobp)) (line-move-invisible (1- (point)))) |
| 2593 | (get-char-property (1- (point)) 'invisible))) | 2594 | (goto-char (previous-char-property-change (point))))))) |
| 2594 | (if (eq buffer-invisibility-spec t) | 2595 | |
| 2595 | prop | 2596 | (line-move-finish (or goal-column temporary-goal-column) opoint))) |
| 2596 | (or (memq prop buffer-invisibility-spec) | ||
| 2597 | (assq prop buffer-invisibility-spec))))) | ||
| 2598 | (if (get-text-property (1- (point)) 'invisible) | ||
| 2599 | (goto-char (or (previous-single-property-change (point) 'invisible) | ||
| 2600 | (point-min))) | ||
| 2601 | (goto-char (previous-overlay-change (point))))) | ||
| 2602 | (setq arg (1+ arg)))) | ||
| 2603 | (let ((buffer-invisibility-spec nil)) | ||
| 2604 | (move-to-column (or goal-column temporary-goal-column)))) | ||
| 2605 | (setq new (point)) | ||
| 2606 | ;; If we are moving into some intangible text, | ||
| 2607 | ;; look for following text on the same line which isn't intangible | ||
| 2608 | ;; and move there. | ||
| 2609 | (setq line-end (save-excursion (end-of-line) (point))) | ||
| 2610 | (setq line-beg (save-excursion (beginning-of-line) (point))) | ||
| 2611 | (let ((after (and (< new (point-max)) | ||
| 2612 | (get-char-property new 'intangible))) | ||
| 2613 | (before (and (> new (point-min)) | ||
| 2614 | (get-char-property (1- new) 'intangible)))) | ||
| 2615 | (when (and before (eq before after) | ||
| 2616 | (not (bolp))) | ||
| 2617 | (goto-char (point-min)) | ||
| 2618 | (let ((inhibit-point-motion-hooks nil)) | ||
| 2619 | (goto-char new)) | ||
| 2620 | (if (<= new line-end) | ||
| 2621 | (setq new (point))))) | ||
| 2622 | ;; NEW is where we want to move to. | ||
| 2623 | ;; LINE-BEG and LINE-END are the beginning and end of the line. | ||
| 2624 | ;; Move there in just one step, from our starting position, | ||
| 2625 | ;; with intangibility and point-motion hooks enabled this time. | ||
| 2626 | (goto-char opoint) | ||
| 2627 | (setq inhibit-point-motion-hooks nil) | ||
| 2628 | (goto-char | ||
| 2629 | (constrain-to-field new opoint nil t 'inhibit-line-move-field-capture)) | ||
| 2630 | ;; If intangibility processing moved us to a different line, | ||
| 2631 | ;; readjust the horizontal position within the line we ended up at. | ||
| 2632 | (when (or (< (point) line-beg) (> (point) line-end)) | ||
| 2633 | (setq new (point)) | ||
| 2634 | (setq inhibit-point-motion-hooks t) | ||
| 2635 | (setq line-end (save-excursion (end-of-line) (point))) | ||
| 2636 | (beginning-of-line) | ||
| 2637 | (setq line-beg (point)) | ||
| 2638 | (let ((buffer-invisibility-spec nil)) | ||
| 2639 | (move-to-column (or goal-column temporary-goal-column))) | ||
| 2640 | (if (<= (point) line-end) | ||
| 2641 | (setq new (point))) | ||
| 2642 | (goto-char (point-min)) | ||
| 2643 | (setq inhibit-point-motion-hooks nil) | ||
| 2644 | (goto-char | ||
| 2645 | (constrain-to-field new opoint nil t | ||
| 2646 | 'inhibit-line-move-field-capture))))) | ||
| 2647 | nil) | 2597 | nil) |
| 2648 | 2598 | ||
| 2599 | (defun line-move-finish (column opoint) | ||
| 2600 | (let ((repeat t)) | ||
| 2601 | (while repeat | ||
| 2602 | ;; Set REPEAT to t to repeat the whole thing. | ||
| 2603 | (setq repeat nil) | ||
| 2604 | |||
| 2605 | ;; Move to the desired column. | ||
| 2606 | (line-move-to-column column) | ||
| 2607 | |||
| 2608 | (let ((new (point)) | ||
| 2609 | (line-beg (save-excursion (beginning-of-line) (point))) | ||
| 2610 | (line-end (save-excursion (end-of-line) (point)))) | ||
| 2611 | |||
| 2612 | ;; Process intangibility within a line. | ||
| 2613 | ;; Move to the chosen destination position from above, | ||
| 2614 | ;; with intangibility processing enabled. | ||
| 2615 | |||
| 2616 | (goto-char (point-min)) | ||
| 2617 | (let ((inhibit-point-motion-hooks nil)) | ||
| 2618 | (goto-char new) | ||
| 2619 | |||
| 2620 | ;; If intangibility moves us to a different (later) place | ||
| 2621 | ;; in the same line, use that as the destination. | ||
| 2622 | (if (<= (point) line-end) | ||
| 2623 | (setq new (point)))) | ||
| 2624 | |||
| 2625 | ;; Now move to the updated destination, processing fields | ||
| 2626 | ;; as well as intangibility. | ||
| 2627 | (goto-char opoint) | ||
| 2628 | (let ((inhibit-point-motion-hooks nil)) | ||
| 2629 | (goto-char | ||
| 2630 | (constrain-to-field new opoint nil t | ||
| 2631 | 'inhibit-line-move-field-capture))) | ||
| 2632 | |||
| 2633 | ;; If intangibility processing moved us to a different line, | ||
| 2634 | ;; retry everything within that new line. | ||
| 2635 | (when (or (< (point) line-beg) (> (point) line-end)) | ||
| 2636 | ;; Repeat the intangibility and field processing. | ||
| 2637 | (setq repeat t)))))) | ||
| 2638 | |||
| 2639 | (defun line-move-to-column (col) | ||
| 2640 | "Try to find column COL, considering invisibility. | ||
| 2641 | This function works only in certain cases, | ||
| 2642 | because what we really need is for `move-to-column' | ||
| 2643 | and `current-column' to be able to ignore invisible text." | ||
| 2644 | (move-to-column col) | ||
| 2645 | |||
| 2646 | (when (and line-move-ignore-invisible | ||
| 2647 | (not (bolp)) (line-move-invisible (1- (point)))) | ||
| 2648 | (let ((normal-location (point)) | ||
| 2649 | (normal-column (current-column))) | ||
| 2650 | ;; If the following character is currently invisible, | ||
| 2651 | ;; skip all characters with that same `invisible' property value. | ||
| 2652 | (while (and (not (eobp)) | ||
| 2653 | (line-move-invisible (point))) | ||
| 2654 | (goto-char (next-char-property-change (point)))) | ||
| 2655 | ;; Have we advanced to a larger column position? | ||
| 2656 | (if (> (current-column) normal-column) | ||
| 2657 | ;; We have made some progress towards the desired column. | ||
| 2658 | ;; See if we can make any further progress. | ||
| 2659 | (line-move-to-column (+ (current-column) (- col normal-column))) | ||
| 2660 | ;; Otherwise, go to the place we originally found | ||
| 2661 | ;; and move back over invisible text. | ||
| 2662 | ;; that will get us to the same place on the screen | ||
| 2663 | ;; but with a more reasonable buffer position. | ||
| 2664 | (goto-char normal-location) | ||
| 2665 | (let ((line-beg (save-excursion (beginning-of-line) (point)))) | ||
| 2666 | (while (and (not (bolp)) (line-move-invisible (1- (point)))) | ||
| 2667 | (goto-char (previous-char-property-change (point) line-beg)))))))) | ||
| 2668 | |||
| 2649 | ;;; Many people have said they rarely use this feature, and often type | 2669 | ;;; Many people have said they rarely use this feature, and often type |
| 2650 | ;;; it by accident. Maybe it shouldn't even be on a key. | 2670 | ;;; it by accident. Maybe it shouldn't even be on a key. |
| 2651 | (put 'set-goal-column 'disabled t) | 2671 | (put 'set-goal-column 'disabled t) |