From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Eli Zaretskii Newsgroups: gmane.emacs.devel Subject: Adjust point to move it off zero-width characters Date: Sat, 06 Aug 2011 17:47:44 +0300 Message-ID: <83bow2wq9b.fsf@gnu.org> Reply-To: Eli Zaretskii NNTP-Posting-Host: lo.gmane.org X-Trace: dough.gmane.org 1312642194 2679 80.91.229.12 (6 Aug 2011 14:49:54 GMT) X-Complaints-To: usenet@dough.gmane.org NNTP-Posting-Date: Sat, 6 Aug 2011 14:49:54 +0000 (UTC) To: emacs-devel@gnu.org Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Sat Aug 06 16:49:50 2011 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([140.186.70.17]) by lo.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1QpiCD-0002Dg-BP for ged-emacs-devel@m.gmane.org; Sat, 06 Aug 2011 16:49:49 +0200 Original-Received: from localhost ([::1]:38601 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QpiCC-0005OI-Ru for ged-emacs-devel@m.gmane.org; Sat, 06 Aug 2011 10:49:48 -0400 Original-Received: from eggs.gnu.org ([140.186.70.92]:45167) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QpiCA-0005O7-Pl for emacs-devel@gnu.org; Sat, 06 Aug 2011 10:49:47 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1QpiC9-0000p1-QM for emacs-devel@gnu.org; Sat, 06 Aug 2011 10:49:46 -0400 Original-Received: from mtaout23.012.net.il ([80.179.55.175]:37794) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QpiC9-0000oN-E0 for emacs-devel@gnu.org; Sat, 06 Aug 2011 10:49:45 -0400 Original-Received: from conversion-daemon.a-mtaout23.012.net.il by a-mtaout23.012.net.il (HyperSendmail v2007.08) id <0LPI00J00GYNO200@a-mtaout23.012.net.il> for emacs-devel@gnu.org; Sat, 06 Aug 2011 17:49:43 +0300 (IDT) Original-Received: from HOME-C4E4A596F7 ([84.228.94.185]) by a-mtaout23.012.net.il (HyperSendmail v2007.08) with ESMTPA id <0LPI00JTCH6UJV40@a-mtaout23.012.net.il> for emacs-devel@gnu.org; Sat, 06 Aug 2011 17:49:43 +0300 (IDT) X-012-Sender: halo1@inter.net.il X-detected-operating-system: by eggs.gnu.org: Solaris 10 (beta) X-Received-From: 80.179.55.175 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:142930 Archived-At: Is the patch below a good idea? If so, is it okay to install it on the trunk? It will allow us to set the glyphless-char-display of LRM, RLM, and the other directional control characters to zero-width and thus make them invisible without having the cursor get "stuck" on them and without using invisible or intangible text properties. === modified file 'src/dispextern.h' --- src/dispextern.h 2011-08-05 11:04:44 +0000 +++ src/dispextern.h 2011-08-06 14:39:22 +0000 @@ -3098,6 +3098,9 @@ extern int cursor_in_mouse_face_p (struc extern void tty_draw_row_with_mouse_face (struct window *, struct glyph_row *, int, int, enum draw_glyphs_face); +extern Lisp_Object Qzero_width; +extern Lisp_Object glyphless_char_display_method (int, struct frame *); + /* Flags passed to try_window. */ #define TRY_WINDOW_CHECK_MARGINS (1 << 0) #define TRY_WINDOW_IGNORE_FONTS_CHANGE (1 << 1) @@ -3113,6 +3116,7 @@ void compute_fringe_widths (struct frame void w32_init_fringe (struct redisplay_interface *); void w32_reset_fringes (void); #endif + /* Defined in image.c */ #ifdef HAVE_WINDOW_SYSTEM === modified file 'src/keyboard.c' --- src/keyboard.c 2011-08-04 17:04:39 +0000 +++ src/keyboard.c 2011-08-06 14:39:31 +0000 @@ -1721,11 +1721,13 @@ adjust_point_for_property (EMACS_INT las user can keep inserting another character at point or keep deleting characters around point. */ int check_composition = ! modified, check_display = 1, check_invisible = 1; + int check_glyphless = !modified; EMACS_INT orig_pt = PT; /* FIXME: cycling is probably not necessary because these properties can't be usefully combined anyway. */ - while (check_composition || check_display || check_invisible) + while (check_composition || check_display || check_invisible + || check_glyphless) { /* FIXME: check `intangible'. */ if (check_composition @@ -1733,7 +1735,7 @@ adjust_point_for_property (EMACS_INT las && (beg = composition_adjust_point (last_pt, PT)) != PT) { SET_PT (beg); - check_display = check_invisible = 1; + check_display = check_invisible = check_glyphless = 1; } check_composition = 0; if (check_display @@ -1752,7 +1754,7 @@ adjust_point_for_property (EMACS_INT las SET_PT (PT < last_pt ? (STRINGP (val) && SCHARS (val) == 0 ? beg - 1 : beg) : end); - check_composition = check_invisible = 1; + check_composition = check_invisible = check_glyphless = 1; } check_display = 0; if (check_invisible && PT > BEGV && PT < ZV) @@ -1823,7 +1825,7 @@ adjust_point_for_property (EMACS_INT las was already in the range: we don't get to choose which end of the range we have to go to. */ : (PT < last_pt ? beg : end)); - check_composition = check_display = 1; + check_composition = check_display = check_glyphless = 1; } #if 0 /* This assertion isn't correct, because SET_PT may end up setting the point to something other than its argument, due to @@ -1836,9 +1838,11 @@ adjust_point_for_property (EMACS_INT las if (!modified && !ellipsis && beg < end) { if (last_pt == beg && PT == end && end < ZV) - (check_composition = check_display = 1, SET_PT (end + 1)); + (check_composition = check_display = check_glyphless = 1, + SET_PT (end + 1)); else if (last_pt == end && PT == beg && beg > BEGV) - (check_composition = check_display = 1, SET_PT (beg - 1)); + (check_composition = check_display = check_glyphless = 1, + SET_PT (beg - 1)); else if (PT == ((PT < last_pt) ? beg : end)) /* We've already moved as far as we can. Trying to go to the other end would mean moving backwards and thus @@ -1851,11 +1855,30 @@ adjust_point_for_property (EMACS_INT las (make_number (PT == beg ? end : beg), Qinvisible, Qnil), !TEXT_PROP_MEANS_INVISIBLE (val))) - (check_composition = check_display = 1, + (check_composition = check_display = check_glyphless = 1, SET_PT (PT == beg ? end : beg)); } } check_invisible = 0; + if (check_glyphless) + { + Lisp_Object glyphless_method; + + check_glyphless = 0; + if (PT >= BEGV && PT < ZV) + { + glyphless_method = + glyphless_char_display_method (FETCH_CHAR (PT_BYTE), + XFRAME (selected_frame)); + + if (EQ (glyphless_method, Qzero_width)) + { + SET_PT (PT > BEGV && PT < last_pt ? PT - 1 : PT + 1); + check_glyphless = 1; + check_composition = check_display = check_invisible = 1; + } + } + } } } === modified file 'src/xdisp.c' --- src/xdisp.c 2011-08-06 11:49:35 +0000 +++ src/xdisp.c 2011-08-06 14:00:43 +0000 @@ -770,7 +770,8 @@ Lisp_Object Qglyphless_char; static Lisp_Object Qglyphless_char_display; /* Method symbols for Vglyphless_char_display. */ -static Lisp_Object Qhex_code, Qempty_box, Qthin_space, Qzero_width; +static Lisp_Object Qhex_code, Qempty_box, Qthin_space; +Lisp_Object Qzero_width; /* Default pixel width of `thin-space' display method. */ #define THIN_SPACE_WIDTH 1 @@ -6019,16 +6020,11 @@ static int (* get_next_element[NUM_IT_ME FACE_FROM_ID ((IT)->f, (IT)->face_id), \ (IT)->string))) - -/* Lookup the char-table Vglyphless_char_display for character C (-1 - if we want information for no-font case), and return the display - method symbol. By side-effect, update it->what and - it->glyphless_method. This function is called from - get_next_display_element for each character element, and from - x_produce_glyphs when no suitable font was found. */ - +/* A subroutine of lookup_glyphless_char_display. Also called from + keyboard.c, to adjust point position when it is on a glyphless + character whose display uses the zero-width method. */ Lisp_Object -lookup_glyphless_char_display (int c, struct it *it) +glyphless_char_display_method (int c, struct frame *f) { Lisp_Object glyphless_method = Qnil; @@ -6039,13 +6035,27 @@ lookup_glyphless_char_display (int c, st { glyphless_method = CHAR_TABLE_REF (Vglyphless_char_display, c); if (CONSP (glyphless_method)) - glyphless_method = FRAME_WINDOW_P (it->f) + glyphless_method = FRAME_WINDOW_P (f) ? XCAR (glyphless_method) : XCDR (glyphless_method); } else glyphless_method = XCHAR_TABLE (Vglyphless_char_display)->extras[0]; } + return glyphless_method; +} + +/* Lookup the char-table Vglyphless_char_display for character C (-1 + if we want information for no-font case), and return the display + method symbol. By side-effect, update it->what and + it->glyphless_method. This function is called from + get_next_display_element for each character element, and from + x_produce_glyphs when no suitable font was found. */ + +Lisp_Object +lookup_glyphless_char_display (int c, struct it *it) +{ + Lisp_Object glyphless_method = glyphless_char_display_method (c, it->f); retry: if (NILP (glyphless_method))