From mboxrd@z Thu Jan 1 00:00:00 1970 Path: main.gmane.org!not-for-mail From: Kenichi Handa Newsgroups: gmane.emacs.devel Subject: problem of display property [Re: list-charset-chars and unicode-bmp] Date: Tue, 28 Jan 2003 20:29:40 +0900 (JST) Sender: emacs-devel-bounces+emacs-devel=quimby.gnus.org@gnu.org Message-ID: <200301281129.UAA16158@etlken.m17n.org> References: <87u1g3atvf.fsf@mimuw.edu.pl> <200301210831.RAA03126@etlken.m17n.org> <871y35kej4.fsf@mimuw.edu.pl> NNTP-Posting-Host: main.gmane.org Mime-Version: 1.0 (generated by SEMI 1.14.3 - "Ushinoya") Content-Type: text/plain; charset=US-ASCII X-Trace: main.gmane.org 1043753812 29969 80.91.224.249 (28 Jan 2003 11:36:52 GMT) X-Complaints-To: usenet@main.gmane.org NNTP-Posting-Date: Tue, 28 Jan 2003 11:36:52 +0000 (UTC) Cc: jsbien@mimuw.edu.pl Return-path: Original-Received: from quimby.gnus.org ([80.91.224.244]) by main.gmane.org with esmtp (Exim 3.35 #1 (Debian)) id 18dU2s-0007nC-00 for ; Tue, 28 Jan 2003 12:36:50 +0100 Original-Received: from monty-python.gnu.org ([199.232.76.173]) by quimby.gnus.org with esmtp (Exim 3.12 #1 (Debian)) id 18dU7X-0000Ma-00 for ; Tue, 28 Jan 2003 12:41:39 +0100 Original-Received: from localhost ([127.0.0.1] helo=monty-python.gnu.org) by monty-python.gnu.org with esmtp (Exim 4.10.13) id 18dU0R-0000GZ-00 for emacs-devel@quimby.gnus.org; Tue, 28 Jan 2003 06:34:19 -0500 Original-Received: from list by monty-python.gnu.org with tmda-scanned (Exim 4.10.13) id 18dTyj-0008Jh-00 for emacs-devel@gnu.org; Tue, 28 Jan 2003 06:32:33 -0500 Original-Received: from mail by monty-python.gnu.org with spam-scanned (Exim 4.10.13) id 18dTwt-0007NS-00 for emacs-devel@gnu.org; Tue, 28 Jan 2003 06:30:42 -0500 Original-Received: from tsukuba.m17n.org ([192.47.44.130]) by monty-python.gnu.org with esmtp (Exim 4.10.13) id 18dTw8-00075O-00 for emacs-devel@gnu.org; Tue, 28 Jan 2003 06:29:52 -0500 Original-Received: from fs.m17n.org (fs.m17n.org [192.47.44.2])h0SBTfk04243; Tue, 28 Jan 2003 20:29:41 +0900 (JST) (envelope-from handa@m17n.org) Original-Received: from etlken.m17n.org (etlken.m17n.org [192.47.44.125]) h0SBTeR26122; Tue, 28 Jan 2003 20:29:40 +0900 (JST) Original-Received: (from handa@localhost) by etlken.m17n.org (8.8.8+Sun/3.7W-2001040620) id UAA16158; Tue, 28 Jan 2003 20:29:40 +0900 (JST) Original-To: d.love@dl.ac.uk In-reply-to: (message from Dave Love on 23 Jan 2003 22:41:54 +0000) User-Agent: SEMI/1.14.3 (Ushinoya) FLIM/1.14.2 (Yagi-Nishiguchi) APEL/10.2 Emacs/21.2.92 (sparc-sun-solaris2.6) MULE/5.0 (SAKAKI) Original-cc: gerd.moellmann@t-online.de Original-cc: emacs-devel@gnu.org X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1b5 Precedence: list List-Id: Emacs development discussions. List-Help: List-Post: List-Subscribe: , List-Archive: List-Unsubscribe: , Errors-To: emacs-devel-bounces+emacs-devel=quimby.gnus.org@gnu.org Xref: main.gmane.org gmane.emacs.devel:11155 X-Report-Spam: http://spam.gmane.org/gmane.emacs.devel:11155 Being a little bit tired of the discussion in emacs-devel, I tried to fix this bug. At first sight, it seems easy ... but it's not ... of course. :-( In article , Dave Love writes: > I think there are comments in the code about my attempt to do that > some time ago. `display' properties behave in strange ways and I seem > to remember that composition doesn't work as you'd hope either. This > isn't specific to the emacs-unicode branch whose redisplay is > seriously buggy anyway. If you want to work on it, I suggest using > the mainline source, but it doesn't seems important to me. That bug can be reproduced as below. (insert "abc" (propertize "." 'display "") "def") When you put cursor on `c' and type C-f, the cursor is placed on `d' instead of `<' of "", but C-x = shows that point is correctly on "." The problem is in this code of set_cursor_from_row. while (glyph < end && !INTEGERP (glyph->object) && (!BUFFERP (glyph->object) || glyph->charpos < pt_old)) { x += glyph->pixel_width; ++glyph; } It skips all glyphs that don't come directy from a buffer. So when point is on ".", at the glyphs comes from display property, instead of stopping at there, it stops at "d". The current members of the struct glyph is not enough to determine the correct cursor position here. We need a new member `buf_charpos' that always holds a buffer position corresponding to each glyph. I'll attach a patch I tried. The strategy is this: At first, record IT_CHARPOS (*IT) in IT->buf_charpos in next_element_from_buffer. Don't change it in the other places (except for reseat_1 and reseat_to_string, they initialize it). Next, in functions that generate GLYPH from IT (e.g append_glyph), copy IT->buf_charpos to GLYPH->buf_charpos. At last, in set_cursor_from_row, check (GLYPH->buf_charpos < pt_old) instead of (GLYPH->charpos < pt_old). It seems that it is working well. But, the comment of the struct glyph says this: /* Glyphs. Be extra careful when changing this structure! Esp. make sure that functions producing glyphs, like x_append_glyph, fill ALL of the glyph structure, and that GLYPH_EQUAL_P compares all display-relevant members of glyphs (not to imply that these are the only things to check when you add a member). */ This makes me nervous about the change. So, I included Gerd in CC:. Gerd, could you help me? What do you think about it? The relevant codes are not changed from 21.1, so I think any new codes added later doesn't affect it. It also means that this bug has been there from 21.1. --- Ken'ichi HANDA handa@m17n.org Index: src/dispextern.h =================================================================== RCS file: /cvsroot/emacs/emacs/src/dispextern.h,v retrieving revision 1.141 diff -u -r1.141 dispextern.h --- src/dispextern.h 17 Nov 2002 23:46:26 -0000 1.141 +++ src/dispextern.h 28 Jan 2003 11:15:11 -0000 @@ -254,6 +254,12 @@ the start of a row. */ int charpos; + /* Buffer position corresponding to this glyph if this glyph is for + displaying a buffer contents. It is used to determine the cursor + position in set_cursor_from_row. The value is simply copied from + it->buf_charpos. */ + int buf_charpos; + /* Lisp object source of this glyph. Currently either a buffer or a string, if the glyph was produced from characters which came from a buffer or a string; or 0 if the glyph was inserted by redisplay @@ -1586,6 +1592,11 @@ /* Function to call to load this structure with the next display element. */ int (* method) P_ ((struct it *it)); + + /* Buffer position if we are iterating over current_buffer, + otherwise -1. The value doesn't change while we are processing + overlay strings, etc. */ + int buf_charpos; /* The next position at which to check for face changes, invisible text, overlay strings, end of text etc., which see. */ Index: src/term.c =================================================================== RCS file: /cvsroot/emacs/emacs/src/term.c,v retrieving revision 1.143 diff -u -r1.143 term.c --- src/term.c 19 Jul 2002 14:37:18 -0000 1.143 +++ src/term.c 28 Jan 2003 11:15:11 -0000 @@ -1630,6 +1630,7 @@ glyph->face_id = it->face_id; glyph->padding_p = i > 0; glyph->charpos = CHARPOS (it->position); + glyph->buf_charpos = it->buf_charpos; glyph->object = it->object; ++it->glyph_row->used[it->area]; Index: src/w32term.c =================================================================== RCS file: /cvsroot/emacs/emacs/src/w32term.c,v retrieving revision 1.177 diff -u -r1.177 w32term.c --- src/w32term.c 22 Jan 2003 23:04:05 -0000 1.177 +++ src/w32term.c 28 Jan 2003 11:15:13 -0000 @@ -1653,6 +1653,7 @@ if (glyph < it->glyph_row->glyphs[area + 1]) { glyph->charpos = CHARPOS (it->position); + glyph->buf_charpos = it->buf_charpos; glyph->object = it->object; glyph->pixel_width = it->pixel_width; glyph->voffset = it->voffset; @@ -1687,6 +1688,7 @@ if (glyph < it->glyph_row->glyphs[area + 1]) { glyph->charpos = CHARPOS (it->position); + glyph->buf_charpos = it->buf_charpos; glyph->object = it->object; glyph->pixel_width = it->pixel_width; glyph->voffset = it->voffset; @@ -1779,6 +1781,7 @@ if (glyph < it->glyph_row->glyphs[area + 1]) { glyph->charpos = CHARPOS (it->position); + glyph->buf_charpos = it->buf_charpos; glyph->object = it->object; glyph->pixel_width = it->pixel_width; glyph->voffset = it->voffset; @@ -1819,6 +1822,7 @@ if (glyph < it->glyph_row->glyphs[area + 1]) { glyph->charpos = CHARPOS (it->position); + glyph->buf_charpos = it->buf_charpos; glyph->object = object; glyph->pixel_width = width; glyph->voffset = it->voffset; Index: src/xdisp.c =================================================================== RCS file: /cvsroot/emacs/emacs/src/xdisp.c,v retrieving revision 1.802 diff -u -r1.802 xdisp.c --- src/xdisp.c 20 Jan 2003 08:54:46 -0000 1.802 +++ src/xdisp.c 28 Jan 2003 11:15:16 -0000 @@ -4105,6 +4105,7 @@ xassert (CHARPOS (pos) >= BEGV && CHARPOS (pos) <= ZV); it->current.pos = it->position = pos; + it->buf_charpos = IT_CHARPOS (*it); XSETBUFFER (it->object, current_buffer); it->end_charpos = ZV; it->dpvec = NULL; @@ -4161,6 +4162,8 @@ it->current.dpvec_index = -1; xassert (charpos >= 0); + it->buf_charpos = -1; + /* If STRING is specified, use its multibyteness, otherwise use the setting of MULTIBYTE, if specified. */ if (multibyte >= 0) @@ -4858,6 +4861,8 @@ xassert (IT_CHARPOS (*it) >= BEGV && IT_CHARPOS (*it) <= it->stop_charpos); + it->buf_charpos = IT_CHARPOS (*it); + if (IT_CHARPOS (*it) >= it->stop_charpos) { if (IT_CHARPOS (*it) >= it->end_charpos) @@ -9477,11 +9482,19 @@ while (glyph < end && !INTEGERP (glyph->object) - && (!BUFFERP (glyph->object) - || glyph->charpos < pt_old)) + && glyph->buf_charpos < pt_old) { x += glyph->pixel_width; ++glyph; + } + + if (glyph != row->glyphs[TEXT_AREA] + && glyph->buf_charpos > pt_old) + { + /* The last skipped glyph strides over point. Go back to that + glyph to display a cursor on it. */ + --glyph; + x -= glyph->pixel_width; } w->cursor.hpos = glyph - row->glyphs[TEXT_AREA]; Index: src/xterm.c =================================================================== RCS file: /cvsroot/emacs/emacs/src/xterm.c,v retrieving revision 1.769 diff -u -r1.769 xterm.c --- src/xterm.c 25 Jan 2003 16:25:38 -0000 1.769 +++ src/xterm.c 28 Jan 2003 11:15:19 -0000 @@ -1455,6 +1455,7 @@ if (glyph < it->glyph_row->glyphs[area + 1]) { glyph->charpos = CHARPOS (it->position); + glyph->buf_charpos = it->buf_charpos; glyph->object = it->object; glyph->pixel_width = it->pixel_width; glyph->voffset = it->voffset; @@ -1488,6 +1489,7 @@ if (glyph < it->glyph_row->glyphs[area + 1]) { glyph->charpos = CHARPOS (it->position); + glyph->buf_charpos = it->buf_charpos; glyph->object = it->object; glyph->pixel_width = it->pixel_width; glyph->voffset = it->voffset; @@ -1579,6 +1581,7 @@ if (glyph < it->glyph_row->glyphs[area + 1]) { glyph->charpos = CHARPOS (it->position); + glyph->buf_charpos = it->buf_charpos; glyph->object = it->object; glyph->pixel_width = it->pixel_width; glyph->voffset = it->voffset; @@ -1618,6 +1621,7 @@ if (glyph < it->glyph_row->glyphs[area + 1]) { glyph->charpos = CHARPOS (it->position); + glyph->buf_charpos = it->buf_charpos; glyph->object = object; glyph->pixel_width = width; glyph->voffset = it->voffset;