From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED!not-for-mail From: Eli Zaretskii Newsgroups: gmane.emacs.bugs Subject: bug#31716: move_it_in_display_line / horizontal scrolling / tab stretch Date: Tue, 05 Jun 2018 17:56:32 +0300 Message-ID: <83zi099t9b.fsf@gnu.org> References: Reply-To: Eli Zaretskii NNTP-Posting-Host: blaine.gmane.org X-Trace: blaine.gmane.org 1528210509 15175 195.159.176.226 (5 Jun 2018 14:55:09 GMT) X-Complaints-To: usenet@blaine.gmane.org NNTP-Posting-Date: Tue, 5 Jun 2018 14:55:09 +0000 (UTC) Cc: 31716@debbugs.gnu.org To: Keith David Bershatsky Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Tue Jun 05 16:55:05 2018 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by blaine.gmane.org with esmtp (Exim 4.84_2) (envelope-from ) id 1fQDMW-0003mQ-3V for geb-bug-gnu-emacs@m.gmane.org; Tue, 05 Jun 2018 16:55:04 +0200 Original-Received: from localhost ([::1]:47342 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fQDOd-0007XR-Ah for geb-bug-gnu-emacs@m.gmane.org; Tue, 05 Jun 2018 10:57:15 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:51035) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fQDOR-0007VJ-BC for bug-gnu-emacs@gnu.org; Tue, 05 Jun 2018 10:57:06 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fQDOQ-0005Wp-2a for bug-gnu-emacs@gnu.org; Tue, 05 Jun 2018 10:57:03 -0400 Original-Received: from debbugs.gnu.org ([208.118.235.43]:55639) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1fQDOP-0005Wb-T9 for bug-gnu-emacs@gnu.org; Tue, 05 Jun 2018 10:57:01 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1fQDOP-0001ya-JU for bug-gnu-emacs@gnu.org; Tue, 05 Jun 2018 10:57:01 -0400 X-Loop: help-debbugs@gnu.org Resent-From: Eli Zaretskii Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Tue, 05 Jun 2018 14:57:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 31716 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: Original-Received: via spool by 31716-submit@debbugs.gnu.org id=B31716.15282105947558 (code B ref 31716); Tue, 05 Jun 2018 14:57:01 +0000 Original-Received: (at 31716) by debbugs.gnu.org; 5 Jun 2018 14:56:34 +0000 Original-Received: from localhost ([127.0.0.1]:35303 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1fQDNy-0001xp-41 for submit@debbugs.gnu.org; Tue, 05 Jun 2018 10:56:34 -0400 Original-Received: from eggs.gnu.org ([208.118.235.92]:59920) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1fQDNv-0001xa-Ia for 31716@debbugs.gnu.org; Tue, 05 Jun 2018 10:56:32 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fQDNn-0005KB-91 for 31716@debbugs.gnu.org; Tue, 05 Jun 2018 10:56:26 -0400 Original-Received: from fencepost.gnu.org ([2001:4830:134:3::e]:45155) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fQDNn-0005K6-4b; Tue, 05 Jun 2018 10:56:23 -0400 Original-Received: from [176.228.60.248] (port=3876 helo=home-c4e4a596f7) by fencepost.gnu.org with esmtpsa (TLS1.2:RSA_AES_256_CBC_SHA1:256) (Exim 4.82) (envelope-from ) id 1fQDNm-0003UJ-Hk; Tue, 05 Jun 2018 10:56:23 -0400 In-reply-to: (message from Keith David Bershatsky on Mon, 04 Jun 2018 17:38:17 -0700) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 208.118.235.43 X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Original-Sender: "bug-gnu-emacs" Xref: news.gmane.org gmane.emacs.bugs:147017 Archived-At: > Date: Mon, 04 Jun 2018 17:38:17 -0700 > From: Keith David Bershatsky > > Step 3. Paste the following Lisp code into a scratch buffer and evaluate the > code. > > (setq display-line-numbers t) > (setq buffer-display-table (make-display-table)) > (aset buffer-display-table > ?\t > (vector (make-glyph-code ?\u00BB 'font-lock-warning-face) > (make-glyph-code ?\t 'highlight))) > (setq tab-width 8) > > Step 4. On a new line in the scratch buffer type: C-q TAB Hello > > Step 5. Place the cursor somewhere on the word "Hello". > > Step 6. Evaluate: (scroll-left 2) > > Step 7. Evaluate: (bug-christmas-ghost) > > OBSERVATIONS: > > A. When w->hscroll is >= 2 and IT is within the tab STRETCH, > move_it_in_display_line_to reports an erroneous it.hpos subsequent to the line > numbers. In this example, it.hpos is reported as being either 0 or 5, even > though the tab STRETCH visibly begins at an it.hpos of 4 when line numbers are > 2 digits wide. > > B. When w->hscroll is >= 2 and IT is within the tab STRETCH, the latter > portion contains one or more it.c ghosts of Christmas future. I.e., the letter > "H" gets returned at several locations along the tab STRETCH. > > EXPECTATIONS / DESIRED BEHAVIOR. > > i. Loops 7 to 12 should report an it.hpos of 4. > > ii. Loops 7 to 12 should report an it.c of 9 (aka a tab character). Summary: Your expectations are incorrect, and the code works as expected, AFAICT. Details: There seems to be a misunderstanding of what MOVE_TO_X means for move_it_in_display_line_to. It sounds like you expect it to end up and the new_x coordinate, or report data about what's at new_x on display. But that's not what MOVE_TO_X actually does. In reality, move_it_in_display_line_to cannot move with 1-pixel granularity, it can only move one "display element" at a time. MOVE_TO_X then tells it to stop at a display element whose display _includes_ the coordinate new_x. A display element that begins at X and has pixel width of WX includes the coordinates in [X..X+WX), i.e. X+WX itself is NOT included. So if, for some display element that starts at X, new_x satisfies the inequality X <= new_x < X+WX then move_it_in_display_line_to will stop at X and return MOVE_X_REACHED. On a GUI frame, a TAB produces a single display element: a stretch glyph whose width is the required TAB width. In this case, it's 56 pixels, 14 of which are invisible due to hscroll. With that knowledge in hand, you need to re-asses the results you obtain. Most importantly, it.current_x tells you where did move_it_in_display_line_to actually stop; it doesn't matter where you asked it to stop (which is new_x). > [IT.HPOS IS 4, NOT 0.] > 7. TAB STRETCH > it.c (9) > char ( ) > it.first_visible_x (14) > w->hscroll (2) > it.hpos (0) > it.first_visible_x (14) > it.current_x (7) <<<<<<<<<<<<<<<<<<<<<<<<<<<<<< > relative_x (28) > new_x (42) > font->space_width (7) > it.pixel_width (49) > it.lnum_pixel_width (28) > rc (MOVE_X_REACHED) > [IT.HPOS IS 4, NOT 0.] > 8. TAB STRETCH > it.c (9) > char ( ) > it.first_visible_x (14) > w->hscroll (2) > it.hpos (0) > it.first_visible_x (14) > it.current_x (7) <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< > relative_x (35) > new_x (49) > font->space_width (7) > it.pixel_width (49) > it.lnum_pixel_width (28) > rc (MOVE_X_REACHED) > [IT.C IS 9, NOT 72; AND, IT.HPOS IS 4, NOT 5.] > 9. TEXT > it.c (72) > char (H) > it.first_visible_x (14) > w->hscroll (2) > it.hpos (5) > it.first_visible_x (14) > it.current_x (84) <<<<<<<<<<<<<<<<<<<<<<<<<<<<<< > relative_x (42) > new_x (56) As you see, the first two calls ended up at the same X coordinate of 7, while the 3rd call stopped at X = 84, and first_visible_x is 14. Since 7 < 14, the first two calls stopped on the TAB, and HPOS is zero because the TAB is hscrolled (HPOS is only advanced for X coordinates beyond first_visible_x). The 3rd call stopped at X = 84, which is the coordinate of 'H', because 84 = 56 + 28, the width needed for 56 pixels of the TAB and 28 pixels of the line number. So the 3rd call reports on 'H', and its HPOS is 5, because 4 columns are taken by the line-number digits and one more is taken by the (partially visible) stretch glyph that displays the TAB. Then you see 4 more calls, all of which stop at X = 84, so they all report on 'H': > [IT.C IS 9, NOT 72; AND, IT.HPOS IS 4, NOT 5.] > 10. TEXT > it.c (72) > char (H) > it.first_visible_x (14) > w->hscroll (2) > it.hpos (5) > it.first_visible_x (14) > it.current_x (84) > relative_x (49) > new_x (63) > font->space_width (7) > it.pixel_width (7) > it.lnum_pixel_width (28) > rc (MOVE_X_REACHED) > [IT.C IS 9, NOT 72; AND, IT.HPOS IS 4, NOT 5.] > 11. TEXT > it.c (72) > char (H) > it.first_visible_x (14) > w->hscroll (2) > it.hpos (5) > it.first_visible_x (14) > it.current_x (84) > relative_x (56) > new_x (70) > font->space_width (7) > it.pixel_width (7) > it.lnum_pixel_width (28) > rc (MOVE_X_REACHED) > [IT.C IS 9, NOT 72; AND, IT.HPOS IS 4, NOT 5.] > 12. TEXT > it.c (72) > char (H) > it.first_visible_x (14) > w->hscroll (2) > it.hpos (5) > it.first_visible_x (14) > it.current_x (84) > relative_x (63) > new_x (77) > font->space_width (7) > it.pixel_width (7) > it.lnum_pixel_width (28) > rc (MOVE_X_REACHED) > [THIS IS THE REAL LETTER "H"] > 13. TEXT > it.c (72) > char (H) > it.first_visible_x (14) > w->hscroll (2) > it.hpos (5) > it.first_visible_x (14) > it.current_x (84) > relative_x (70) > new_x (84) > font->space_width (7) > it.pixel_width (7) > it.lnum_pixel_width (28) > rc (MOVE_X_REACHED) IOW, these 'H' are not "ghosts", they are the actual character displayed at the same location X = 84. You just get 4 reports on the same character because move_it_in_display_line_to is at the same coordinate. So I see nothing wrong here. Note that on TTY frames, a TAB is displayed as several separate SPC characters, so in that case you _can_ move by individual increments inside the TAB display.