unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* Adjust point to move it off zero-width characters
@ 2011-08-06 14:47 Eli Zaretskii
  2011-08-07 16:13 ` Stefan Monnier
  0 siblings, 1 reply; 8+ messages in thread
From: Eli Zaretskii @ 2011-08-06 14:47 UTC (permalink / raw)
  To: emacs-devel

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))




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

end of thread, other threads:[~2011-08-08  4:12 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-08-06 14:47 Adjust point to move it off zero-width characters Eli Zaretskii
2011-08-07 16:13 ` Stefan Monnier
2011-08-07 16:39   ` Eli Zaretskii
2011-08-07 16:46     ` Eli Zaretskii
2011-08-07 17:10       ` Eli Zaretskii
2011-08-08  0:50     ` Stefan Monnier
2011-08-08  3:02       ` Eli Zaretskii
2011-08-08  4:12         ` Stefan Monnier

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).