unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* Test to determine character left-overhangs a tab stretch.
@ 2018-11-12  2:06 Keith David Bershatsky
  2018-11-12 16:13 ` Eli Zaretskii
  0 siblings, 1 reply; 8+ messages in thread
From: Keith David Bershatsky @ 2018-11-12  2:06 UTC (permalink / raw)
  To: Emacs Devel

I am working on feature requests #22873 (multiple fake cursors); and, #17684 (crosshairs).

Fake cursors are placed on a line in the order of left to right.  ns/x_draw_window_cursor calls draw_phys_cursor_glyph, which calls draw_glyphs.

Certain wide characters to the immediate right of a tab stretch cause the tab stretch to be redrawn -- erasing the fake cursors that were previously placed along the tab stretch.  Here is a screenshot depicting a tab stretch after the cursors have been erased from it -- the tab stretch had red hbar cursors before they were erased:

https://www.lawlist.com/images/glyph_overhang_001.png

How can programmatically test for this situation?

Thanks,

Keith



^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Test to determine character left-overhangs a tab stretch.
  2018-11-12  2:06 Keith David Bershatsky
@ 2018-11-12 16:13 ` Eli Zaretskii
  0 siblings, 0 replies; 8+ messages in thread
From: Eli Zaretskii @ 2018-11-12 16:13 UTC (permalink / raw)
  To: Keith David Bershatsky; +Cc: emacs-devel

> Date: Sun, 11 Nov 2018 18:06:10 -0800
> From: Keith David Bershatsky <esq@lawlist.com>
> 
> I am working on feature requests #22873 (multiple fake cursors); and, #17684 (crosshairs).
> 
> Fake cursors are placed on a line in the order of left to right.  ns/x_draw_window_cursor calls draw_phys_cursor_glyph, which calls draw_glyphs.
> 
> Certain wide characters to the immediate right of a tab stretch cause the tab stretch to be redrawn -- erasing the fake cursors that were previously placed along the tab stretch.  Here is a screenshot depicting a tab stretch after the cursors have been erased from it -- the tab stretch had red hbar cursors before they were erased:
> 
> https://www.lawlist.com/images/glyph_overhang_001.png
> 
> How can programmatically test for this situation?

Not sure what you are asking, but the logic for deciding when to
redraw due to overhang is entirely inside draw_glyphs, so you could do
the same as what it does.



^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Test to determine character left-overhangs a tab stretch.
@ 2018-11-12 22:22 Keith David Bershatsky
  0 siblings, 0 replies; 8+ messages in thread
From: Keith David Bershatsky @ 2018-11-12 22:22 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel

Thank you, Eli, reviewing and responding to this particular thread.

I will continue studying draw_glyphs in the coming days with an eye towards pinpointing the circumstance when a preceding tab stretch is drawn anew upon a cursor being placed on the subsequent character.

As always, your help is greatly appreciated.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

> Date: [11-12-2018 08:13:29] <12 Nov 2018 18:13:29 +0200>
> From: Eli Zaretskii <eliz@gnu.org>
> To: Keith David Bershatsky <esq@lawlist.com>
> CC: emacs-devel@gnu.org
> Subject: Re: Test to determine character left-overhangs a tab stretch.
> 
> * * *
> 
> Not sure what you are asking, but the logic for deciding when to
> redraw due to overhang is entirely inside draw_glyphs, so you could do
> the same as what it does.



^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Test to determine character left-overhangs a tab stretch.
@ 2018-11-13 19:11 Keith David Bershatsky
  2018-11-13 20:08 ` Eli Zaretskii
  0 siblings, 1 reply; 8+ messages in thread
From: Keith David Bershatsky @ 2018-11-13 19:11 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel

I was able to locate the exact location where the tab stretch is being redrawn when I place a fake cursor on the following character; however, my test is causing Emacs to crash.  I tried putting in two additional checks in an effort to void a crash (first_glyph != NULL && first_glyph->type != NULL), but the crash still occurs.  Any pointers on how to refine my test to avoid crashing Emacs would be greatly appreciated.  A partial GDB printout follows the relevant xdisp.c snippet below.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; xdisp.c snippet

      /* Prepend glyph strings for glyphs in front of the first glyph
	 string that are overwritten because of the first glyph
	 string's left overhang.  The background of all strings
	 prepended must be drawn because the first glyph string
	 draws over it.  */
      i = left_overwritten (head);

      bool skip_p = false;
      int beg = i;
      if (w->mc.glyph_flavor == MC_GLYPH
          || w->mc.glyph_flavor == MC_GLYPHLESS
          || w->mc.glyph_flavor == MC_GLYPH_TAB)
        while (beg < start)
          {
            struct glyph *first_glyph = (row)->glyphs[area] + beg;
            if (first_glyph != NULL
                && first_glyph->type != NULL)
              {
                 switch (first_glyph->type)
                {
                  case CHAR_GLYPH:
                    break;
                  case COMPOSITE_GLYPH:
                    break;
                  case STRETCH_GLYPH:
                    {
                      skip_p = true;
                      break;
                    }
                  case IMAGE_GLYPH:
                    break;
                }
              }
            beg += 1;
          }

      if (i >= 0
          && !skip_p)
	{
	  enum draw_glyphs_face overlap_hl;

	  /* If this row contains mouse highlighting, attempt to draw
	     the overlapped glyphs with the correct highlight.  This
	     code fails if the overlap encompasses more than one glyph
	     and mouse-highlight spans only some of these glyphs.
	     However, making it work perfectly involves a lot more
	     code, and I don't know if the pathological case occurs in
	     practice, so we'll stick to this for now.  --- cyd  */

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; GDB

Program received signal SIGSEGV, Segmentation fault.
0x000000010009c6cb in draw_glyphs (w=0x11e373c30, x=186, row=0x102f6fa00, 
    area=TEXT_AREA, start=15, end=16, hl=DRAW_CURSOR, overlaps=0)
    at xdisp.c:31453
warning: Source file is more recent than executable.
31453	                {

(gdb) bt
#0  0x000000010009c6cb in draw_glyphs (w=0x11e373c30, x=186, row=0x102f6fa00, 
    area=TEXT_AREA, start=15, end=16, hl=DRAW_CURSOR, overlaps=0)
    at xdisp.c:31453
#1  0x00000001000a9361 in draw_phys_cursor_glyph (w=0x11e373c30, 
    row=0x102f6fa00, hl=DRAW_CURSOR) at xdisp.c:34272
#2  0x00000001002c2828 in ns_draw_window_cursor (w=0x11e373c30, 
    glyph_row=0x102f6fa00, x=165, y=444, cursor_type=BAR_CURSOR, 
    cursor_width=1, on_p=true, active_p=true) at nsterm.m:3077

* * *

(gdb) frame 0
#0  0x000000010009c6cb in draw_glyphs (w=0x11e373c30, x=186, row=0x102f6fa00, 
    area=TEXT_AREA, start=15, end=16, hl=DRAW_CURSOR, overlaps=0)
    at xdisp.c:31453
31453	                {

(gdb) print first_glyph->type
Cannot access memory at address 0x1227fffb8

(gdb) print first_glyph
$1 = (struct glyph *) 0x1227fffb8



^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Test to determine character left-overhangs a tab stretch.
  2018-11-13 19:11 Keith David Bershatsky
@ 2018-11-13 20:08 ` Eli Zaretskii
  0 siblings, 0 replies; 8+ messages in thread
From: Eli Zaretskii @ 2018-11-13 20:08 UTC (permalink / raw)
  To: Keith David Bershatsky; +Cc: emacs-devel

> Date:  Tue, 13 Nov 2018 11:11:49 -0800
> From:  Keith David Bershatsky <esq@lawlist.com>
> Cc:  emacs-devel@gnu.org
> 
> Program received signal SIGSEGV, Segmentation fault.
> 0x000000010009c6cb in draw_glyphs (w=0x11e373c30, x=186, row=0x102f6fa00, 
>     area=TEXT_AREA, start=15, end=16, hl=DRAW_CURSOR, overlaps=0)
>     at xdisp.c:31453
> warning: Source file is more recent than executable.
> 31453	                {

You are asking for the impossible: (1) you don't say which line in the
snippet is line 31453; (2) GDB complains that source is more recent
than the binary, so the line number it shows, 31453, is probably
inaccurate; and (3) you don't tell what did you change in the original
code which started to cause the crashes.  Please have mercy on my poor
soul!



^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Test to determine character left-overhangs a tab stretch.
@ 2018-11-13 20:57 Keith David Bershatsky
  2018-11-14 15:33 ` Eli Zaretskii
  0 siblings, 1 reply; 8+ messages in thread
From: Keith David Bershatsky @ 2018-11-13 20:57 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel

Thank you Eli for helping out with this particular issue.  I think the problem is that first_glyph->type (in the following test) is sometimes invalid and that is what causes the crash.  The test is designed to skip over the area of code when a tab stretch would normally be drawn anew due to the next glyph having a left overhang.

Last Commit : Tue Nov 13 22:01:57 2018 +0200
            : Eli Zaretskii <eliz@gnu.org>
            : 4a5a17507fe1e12ee02c174350edc479fb01ac01
            : Fix recent change in fileio.c

diff --git a/src/xdisp.c b/src/xdisp.c
index fa7691c..198a516 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -26841,7 +26841,45 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row,
 	 prepended must be drawn because the first glyph string
 	 draws over it.  */
       i = left_overwritten (head);
-      if (i >= 0)
+
+
+/* *************************************************************************** */
+/* MULTIPLE CURSORS */
+
+      bool skip_p = false;
+      int beg = i;
+
+      if (hl == DRAW_CURSOR)
+        while (beg < start)
+          {
+            struct glyph *first_glyph = (row)->glyphs[area] + beg;
+            if (first_glyph != NULL
+                && first_glyph->type != NULL)
+              {
+                 switch (first_glyph->type)
+                {
+                  case CHAR_GLYPH:
+                    break;
+                  case COMPOSITE_GLYPH:
+                    break;
+                  case STRETCH_GLYPH:
+                    {
+                      skip_p = true;
+                      break;
+                    }
+                  case IMAGE_GLYPH:
+                    break;
+                }
+              }
+            beg += 1;
+          }
+
+      if (i >= 0
+          && !skip_p)
+
+/* *************************************************************************** */
+
+
 	{
 	  enum draw_glyphs_face overlap_hl;



^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: Test to determine character left-overhangs a tab stretch.
  2018-11-13 20:57 Test to determine character left-overhangs a tab stretch Keith David Bershatsky
@ 2018-11-14 15:33 ` Eli Zaretskii
  0 siblings, 0 replies; 8+ messages in thread
From: Eli Zaretskii @ 2018-11-14 15:33 UTC (permalink / raw)
  To: Keith David Bershatsky; +Cc: emacs-devel

> Date:  Tue, 13 Nov 2018 12:57:08 -0800
> From:  Keith David Bershatsky <esq@lawlist.com>
> Cc:  emacs-devel@gnu.org
> 
> Thank you Eli for helping out with this particular issue.  I think the problem is that first_glyph->type (in the following test) is sometimes invalid and that is what causes the crash.  The test is designed to skip over the area of code when a tab stretch would normally be drawn anew due to the next glyph having a left overhang.
> 
> Last Commit : Tue Nov 13 22:01:57 2018 +0200
>             : Eli Zaretskii <eliz@gnu.org>
>             : 4a5a17507fe1e12ee02c174350edc479fb01ac01
>             : Fix recent change in fileio.c
> 
> diff --git a/src/xdisp.c b/src/xdisp.c
> index fa7691c..198a516 100644
> --- a/src/xdisp.c
> +++ b/src/xdisp.c
> @@ -26841,7 +26841,45 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row,
>  	 prepended must be drawn because the first glyph string
>  	 draws over it.  */
>        i = left_overwritten (head);
> -      if (i >= 0)

left_overwritten can return a negative value, in which case this:

> +      bool skip_p = false;
> +      int beg = i;
> +
> +      if (hl == DRAW_CURSOR)
> +        while (beg < start)
> +          {
> +            struct glyph *first_glyph = (row)->glyphs[area] + beg;
> +            if (first_glyph != NULL
> +                && first_glyph->type != NULL)

attempts to dereference a pointer that is before the beginning of
row->glyphs[area], and you get a segfault.  I think your code should
be inside the "if (i >= 0)" clause.

Stepping back, I'm not sure what you do is a good idea.  Redrawing
neighboring glyphs due to overhanging is done for a reason, so
skipping it might well produce incorrect display.  I advice against
that.



^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Test to determine character left-overhangs a tab stretch.
@ 2018-11-14 18:25 Keith David Bershatsky
  0 siblings, 0 replies; 8+ messages in thread
From: Keith David Bershatsky @ 2018-11-14 18:25 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel

Thank you very much for solving the mystery as to the segfault -- greatly appreciated!!!

I agree that merely skipping over that section of code in this situation is not a good idea.  Now that a reliable test exists, I can begin working on devising a method to redraw the fake cursors along the tab stretch after it gets drawn anew.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

> Date: [11-14-2018 07:33:56] <14 Nov 2018 17:33:56 +0200>
> From: Eli Zaretskii <eliz@gnu.org>
> To: Keith David Bershatsky <esq@lawlist.com>
> CC: emacs-devel@gnu.org
> Subject: Re: Test to determine character left-overhangs a tab stretch.
> 
> * * *
> 
> Stepping back, I'm not sure what you do is a good idea.  Redrawing
> neighboring glyphs due to overhanging is done for a reason, so
> skipping it might well produce incorrect display.  I advice against
> that.



^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2018-11-14 18:25 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-11-13 20:57 Test to determine character left-overhangs a tab stretch Keith David Bershatsky
2018-11-14 15:33 ` Eli Zaretskii
  -- strict thread matches above, loose matches on Subject: below --
2018-11-14 18:25 Keith David Bershatsky
2018-11-13 19:11 Keith David Bershatsky
2018-11-13 20:08 ` Eli Zaretskii
2018-11-12 22:22 Keith David Bershatsky
2018-11-12  2:06 Keith David Bershatsky
2018-11-12 16:13 ` Eli Zaretskii

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).