Subject: Re: bug#30226: Fixing it->pixel_width / it->current_x when tabs and line numbers.

From: Keith David Bershatsky <[email-masked]>
Date: Wed, 31 Jan 2018 00:03:09 -0800

Thank you, Eli, for teaching me how to mathematically calculate the pixel-width of the tab STRETCH in this example ["C-q TAB Hello-world" and w->hscroll >= 2].  Greatly appreciated!  :)

A couple of additional questions whenever you have the time . . . .

I.  In the context of this particular example ["C-q TAB Hello-world" and w->hscroll >= 2], we cannot calculate the _relative_ X by subtracting it.first_visible_x from it.current_x (as would generally be the case).  Is there a better way to calculate the _relative_ X instead of keeping track of _every_ visual pixel-width to the left of the current _relative_ X that we are seeking?

(For example, pgrowx and dump_glyph_row both just keep track of the prior _relative_ X and they add the prior pixel-width to derive the current _relative_ X.)

II.  In a slightly different fact pattern with two (2) consecutive tabs ["C-q TAB C-q TAB Hello-world" and w->hscroll >= 2], the tab STRETCH of the second tab _visually_ disappears and dump_glyph_row reports that its width is -1.  Is there a way to programmatically know whether the tab STRETCH is -1 when we are using move_it_in_display_line_to?

The following are the results of two calls to the revised function bug-30226 using this new hypothetical with two (2) consecutive tabs.  And, I added a printout of pgrowx when w->hscroll == 2.

A.  This is the first (1st) time we call the revised bug-30226 [w->hscroll == 1]:

1.  NOTHING
    it.c (0)
    w->hscroll (1)
    it.hpos (0) 
    it.current_x (0)
    it.pixel_width (0)

2.  TAB CHARACTER
    it.c (187)
    w->hscroll (1)
    it.hpos (0) 
    it.current_x (0)
    it.pixel_width (7)

3.  TAB STRETCH
    it.c (9)
    w->hscroll (1)
    it.hpos (0) 
    it.current_x (7)
    it.pixel_width (49)

4.  TAB STRETCH
    it.c (9)
    w->hscroll (1)
    it.hpos (4) 
    it.current_x (35)
    it.pixel_width (42)

5.  TAB CHARACTER
    it.c (187)
    w->hscroll (1)
    it.hpos (5) 
    it.current_x (77)
    it.pixel_width (7)

6.  TAB STRETCH
    it.c (9)
    w->hscroll (1)
    it.hpos (6) 
    it.current_x (84)
    it.pixel_width (49)

7.  TEXT
    it.c (72)
    w->hscroll (1)
    it.hpos (7) 
    it.current_x (133)
    it.pixel_width (7)

* * *

Row     Start       End Used oE><\CTZFesm     X    Y    W    H    V    A    P
==============================================================================
 12       455       468   19 111000110000     0  192  210   16   16   12   12
           -1        -1	    0
           -1        -1
           -1        -1
 Glyph#  Type       Pos   O   W     Code      C Face LR
      0     C        -1   0   7 0x000020          29 00
      1     C        -1   0   7 0x000031      1   29 00
      2     C        -1   0   7 0x000033      3   29 00
      3     C        -1   0   7 0x000020          29 00
      4     S       455   B  42 0x000000          31 00
      5     C       456   B   7 0x0000bb      .   32 00
      6     S       456   B  49 0x000000          31 00
      7     C       457   B   7 0x000048      H    0 00
      8     C       458   B   7 0x000065      e    0 00
      9     C       459   B   7 0x00006c      l    0 00
     10     C       460   B   7 0x00006c      l    0 00
     11     C       461   B   7 0x00006f      o    0 00
     12     C       462   B   7 0x00002d      -    0 00
     13     C       463   B   7 0x000077      w    0 00
     14     C       464   B   7 0x00006f      o    0 00
     15     C       465   B   7 0x000072      r    0 00
     16     C       466   B   7 0x00006c      l    0 00
     17     C       467   B   7 0x000064      d    0 00
     18     C         0   0   7 0x000020           0 00

B.  This is the second (2nd) time we call the revised bug-30226 [w->hscroll == 2]:

1.  NOTHING
    it.c (0)
    w->hscroll (2)
    it.hpos (0) 
    it.current_x (0)
    it.pixel_width (0)

2.  TAB CHARACTER
    it.c (187)
    w->hscroll (2)
    it.hpos (0) 
    it.current_x (0)
    it.pixel_width (7)

3.  TAB STRETCH
    it.c (9)
    w->hscroll (2)
    it.hpos (0) 
    it.current_x (7)
    it.pixel_width (49)

4.  TAB CHARACTER
    it.c (187)
    w->hscroll (2)
    it.hpos (5) 
    it.current_x (84)
    it.pixel_width (7)

5.  TAB STRETCH
    it.c (9)
    w->hscroll (2)
    it.hpos (6) 
    it.current_x (91)
    it.pixel_width (35)

6.  TEXT
    it.c (72)
    w->hscroll (2)
    it.hpos (7) 
    it.current_x (126)
    it.pixel_width (7)

* * *

Row     Start       End Used oE><\CTZFesm     X    Y    W    H    V    A    P
==============================================================================
 12       455       468   19 111000110000     0  192  153   16   16   12   12
           -1        -1	    0
           -1        -1
           -1        -1
 Glyph#  Type       Pos   O   W     Code      C Face LR
      0     C        -1   0   7 0x000020          29 00
      1     C        -1   0   7 0x000031      1   29 00
      2     C        -1   0   7 0x000033      3   29 00
      3     C        -1   0   7 0x000020          29 00
      4     S       455   B  35 0x000000          31 00
      5     C       456   B   7 0x0000bb      .   32 00
      6     S       456   B  -1 0x000000          31 00
      7     C       457   B   7 0x000048      H    0 00
      8     C       458   B   7 0x000065      e    0 00
      9     C       459   B   7 0x00006c      l    0 00
     10     C       460   B   7 0x00006c      l    0 00
     11     C       461   B   7 0x00006f      o    0 00
     12     C       462   B   7 0x00002d      -    0 00
     13     C       463   B   7 0x000077      w    0 00
     14     C       464   B   7 0x00006f      o    0 00
     15     C       465   B   7 0x000072      r    0 00
     16     C       466   B   7 0x00006c      l    0 00
     17     C       467   B   7 0x000064      d    0 00
     18     C         0   0   7 0x000020           0 00

PGROWX:  pgrowx glyph_row

TEXT: 19 glyphs
  0    0: CHAR[ ] pos=-1 blev=2,btyp=EN w=7 a+d=12+4 face=31 MB AVOID
  1    7: CHAR[1] pos=-1 blev=2,btyp=EN w=7 a+d=12+4 face=31 MB AVOID
  2   14: CHAR[4] pos=-1 blev=2,btyp=EN w=7 a+d=12+4 face=31 MB AVOID
  3   21: CHAR[ ] pos=-1 blev=2,btyp=EN w=7 a+d=12+4 face=31 MB AVOID
  4   28: STRETCH[16+12] pos=456 w=35 a+d=12+4 face=33 MB
  5   63: CHAR[0xbb] pos=457 blev=0,btyp=L w=7 a+d=12+4 face=34 MB
  6   70: STRETCH[16+12] pos=457 w=-1 a+d=12+4 face=33 MB
  7   69: CHAR[H] pos=458 blev=0,btyp=L w=7 a+d=12+4 MB
  8   76: CHAR[e] pos=459 blev=0,btyp=L w=7 a+d=12+4 MB
  9   83: CHAR[l] pos=460 blev=0,btyp=L w=7 a+d=12+4 MB
 10   90: CHAR[l] pos=461 blev=0,btyp=L w=7 a+d=12+4 MB
 11   97: CHAR[o] pos=462 blev=0,btyp=L w=7 a+d=12+4 MB
 12  104: CHAR[-] pos=463 blev=0,btyp=L w=7 a+d=12+4 MB
 13  111: CHAR[w] pos=464 blev=0,btyp=L w=7 a+d=12+4 MB
 14  118: CHAR[o] pos=465 blev=0,btyp=L w=7 a+d=12+4 MB
 15  125: CHAR[r] pos=466 blev=0,btyp=L w=7 a+d=12+4 MB
 16  132: CHAR[l] pos=467 blev=0,btyp=L w=7 a+d=12+4 MB
 17  139: CHAR[d] pos=468 blev=0,btyp=L w=7 a+d=12+4 MB
 18  146: CHAR[ ] pos=0 blev=0,btyp=B w=7 a+d=12+4 MB

DEFUN ("bug-30226", Fbug_30226, Sbug_30226, 0, 0, 0,
       doc: /* Debug the pixel-width of a stretch tab. */)
  (void)
{
  Fscroll_left (make_number (1), Qnil);
  struct window *w = decode_live_window (selected_window);
  struct frame *f = XFRAME (w->frame);
  struct it it;
  void *itdata = bidi_shelve_cache ();
  enum move_it_result rc = MOVE_X_REACHED;
  struct text_pos start_text_position;
  int count = 1;
  int previous_char = 0;
  int previous_x = 0;
/* ******************************************************************************
                      START DISPLAY -- w->start
****************************************************************************** */
  /* Begin the journey at w->start. */
  SET_TEXT_POS_FROM_MARKER (start_text_position, w->start);
  start_display (&it, w, start_text_position);
  struct face *face = FACE_FROM_ID (it.f, it.face_id);
  struct font *font = face->font;
/* ******************************************************************************
                GO TO THE BEGINNING OF THE CURRENT LINE.
****************************************************************************** */
  /* Place the IT on the current line containing PT. */
  int voffset = (WINDOW_HEADER_LINE_HEIGHT (w) > 0
                 && w->output_cursor.vpos > 0)
                  ? w->output_cursor.vpos - 1
                  : w->output_cursor.vpos;
  if (voffset > 0)
    move_it_by_lines (&it, voffset);
  struct glyph_row *glyph_row = MATRIX_ROW (w->current_matrix, it.vpos);
/* ******************************************************************************
             MOVE IT OVER EACH CHARACTER ON THE CURRENT LINE.
****************************************************************************** */
  while (true)
    {
      if (ITERATOR_AT_END_OF_LINE_P (&it)
          || FETCH_BYTE (IT_BYTEPOS (it)) == '\n'
          || rc == MOVE_POS_MATCH_OR_ZV)
        break;
/* ******************************************************************************
                       DUMP RELEVANT GLYPH INFORMATION
****************************************************************************** */
      if (w->hscroll > 0)
        {
          int w_hscroll = w->hscroll;
          fprintf (stderr, "\n%d.  %s\n\
    it.c (%d)\n\
    w->hscroll (%d)\n\
    it.hpos (%d) \n\
    it.current_x (%d)\n\
    it.pixel_width (%d)\n",
                 count,
                 (it.c == 0
                   ? "NOTHING"
                   : it.c == 187
                     ? "TAB CHARACTER"
                   : it.c == '\t'
                     ? "TAB STRETCH"
                   : "TEXT"),
                 it.c,
                 w_hscroll,
                 it.hpos,
                 it.current_x,
                 it.pixel_width);
        }
/* ******************************************************************************
                       MOVE IT -- INCREMENT == IT.PIXEL_WIDTH 
****************************************************************************** */
      previous_char = it.c;
      previous_x = it.current_x;
      rc = move_it_in_display_line_to (&it, ZV, it.current_x + it.pixel_width,
                                       MOVE_TO_POS | MOVE_TO_X);
      count = count + 1;
      if (rc == MOVE_LINE_CONTINUED)
        break;
      if (it.current_x - it.first_visible_x + font->space_width >=
          window_box_width (w, TEXT_AREA))
        break;
    }
/* ******************************************************************************
                         REDISPLAY AND DUMP_GLPYH_ROW
****************************************************************************** */
  redisplay_internal ();
  fprintf (stderr, "\n");
  dump_glyph_row (glyph_row, it.vpos, 2);
  bidi_unshelve_cache (itdata, false);
  return Qnil;
}