]> git.eshelyaron.com Git - emacs.git/commitdiff
Handle glyphless characters on tty.
authorKenichi Handa <handa@m17n.org>
Mon, 1 Nov 2010 04:09:26 +0000 (13:09 +0900)
committerKenichi Handa <handa@m17n.org>
Mon, 1 Nov 2010 04:09:26 +0000 (13:09 +0900)
lisp/ChangeLog
lisp/faces.el
src/ChangeLog
src/coding.c
src/dispextern.h
src/term.c
src/termhooks.h
src/xdisp.c

index 46160f878b32cfa4517114342b180302f7ee9135..5d2e442a1c1808de7f7f88b11dd231a3975eb124 100644 (file)
@@ -1,3 +1,7 @@
+2010-11-01  Kenichi Handa  <handa@m17n.org>
+
+       * faces.el (glyphless-char): Inherit underline for tty.
+
 2010-10-28  Kenichi Handa  <handa@m17n.org>
 
        Implement various display methods for glyphless characters.
index 562bde6ed41d72a394be621ff936ad99e01845b5..5e421f3f70acdec7218fb7c7607e6cf9256aeabb 100644 (file)
@@ -2483,7 +2483,9 @@ Note: Other faces cannot inherit from the cursor face."
   "Face to highlight argument names in *Help* buffers."
   :group 'help)
 
-(defface glyphless-char '((t :height 0.6))
+(defface glyphless-char
+  '((((type tty)) :inherit underline)
+    (t :height 0.6))
   "Face for displaying non-graphic characters (e.g. U+202A (LRE)).
 It is used for characters of no fonts too."
   :version "24.1"
index eecad1f968941b7d7946b08d861855886cf7e0c2..2d1ed5a96fb6385a583953b9856eb1cc454f3777 100644 (file)
@@ -1,3 +1,21 @@
+2010-11-01  Kenichi Handa  <handa@m17n.org>
+
+       * dispextern.h (lookup_glyphless_char_display): Extern it.
+
+       * termhooks.h (struct terminal): New member charset_list.
+
+       * coding.c (Fset_terminal_coding_system_internal): Set the
+       `charset_list' member of struct terminal.
+
+       * term.c (produce_glyphs): Handle the case it->what ==
+       IT_GLYPHLESS.
+       (append_glyphless_glyph, produce_glyphless_glyph): New functions.
+
+       * xdisp.c (lookup_glyphless_char_display): Make it non-static.
+       (lookup_glyphless_char_display): Set it->what at the end.
+       (last_glyphless_glyph_frame, last_glyphless_glyph_face_id)
+       (last_glyphless_glyph_merged_face_id): Make them non-static.
+
 2010-10-29  Kenichi Handa  <handa@m17n.org>
 
        * w32gui.h (STORE_XCHAR2B, XCHAR2B_BYTE1, XCHAR2B_BYTE2): Surround
index 7a3bc40b9c7b1fdd1382b861d658e5a3cc419cdf..59deb22a3d7441bd506c52b105fbf2d23b03ef87 100644 (file)
@@ -9297,7 +9297,8 @@ DEFUN ("set-terminal-coding-system-internal", Fset_terminal_coding_system_intern
        doc: /* Internal use only.  */)
   (Lisp_Object coding_system, Lisp_Object terminal)
 {
-  struct coding_system *terminal_coding = TERMINAL_TERMINAL_CODING (get_terminal (terminal, 1));
+  struct terminal *term = get_terminal (terminal, 1);
+  struct coding_system *terminal_coding = TERMINAL_TERMINAL_CODING (term);
   CHECK_SYMBOL (coding_system);
   setup_coding_system (Fcheck_coding_system (coding_system), terminal_coding);
   /* We had better not send unsafe characters to terminal.  */
@@ -9306,6 +9307,10 @@ DEFUN ("set-terminal-coding-system-internal", Fset_terminal_coding_system_intern
   terminal_coding->common_flags &= ~CODING_ANNOTATE_COMPOSITION_MASK;
   terminal_coding->src_multibyte = 1;
   terminal_coding->dst_multibyte = 0;
+  if (terminal_coding->common_flags & CODING_REQUIRE_ENCODING_MASK)
+    term->charset_list = coding_charset_list (terminal_coding);
+  else
+    term->charset_list = Fcons (Qascii, Qnil);
   return Qnil;
 }
 
index af09ec5d3de654c20fb671ddacfb836a29b90b67..c2eeb6ec52703db83fcfbfc59d3655289e14a210 100644 (file)
@@ -3021,7 +3021,7 @@ extern EMACS_INT underline_minimum_offset;
 extern Lisp_Object Vglyphless_char_display;
 
 extern void reseat_at_previous_visible_line_start (struct it *);
-
+extern Lisp_Object lookup_glyphless_char_display (int, struct it *);
 extern int calc_pixel_width_or_height (double *, struct it *, Lisp_Object,
                                        struct font *, int, int *);
 
index 4baea231de3ce815a23ddabbe37d7d11c69b6296..7593f02e607ef67c0b51683ec34f1200c6a7fb7b 100644 (file)
@@ -1501,6 +1501,8 @@ static void append_glyph (struct it *);
 static void produce_stretch_glyph (struct it *);
 static void append_composite_glyph (struct it *);
 static void produce_composite_glyph (struct it *);
+static void append_glyphless_glyph (struct it *, int, char *);
+static void produce_glyphless_glyph (struct it *, int, Lisp_Object);
 
 /* Append glyphs to IT's glyph_row.  Called from produce_glyphs for
    terminal frames if IT->glyph_row != NULL.  IT->char_to_display is
@@ -1609,6 +1611,12 @@ produce_glyphs (struct it *it)
       goto done;
     }
 
+  if (it->what == IT_GLYPHLESS)
+    {
+      produce_glyphless_glyph (it, 0, Qnil);
+      goto done;
+    }
+
   if (it->char_to_display >= 040 && it->char_to_display < 0177)
     {
       it->pixel_width = it->nglyphs = 1;
@@ -1660,11 +1668,22 @@ produce_glyphs (struct it *it)
     }
   else
     {
-      it->pixel_width = CHAR_WIDTH (it->char_to_display);
-      it->nglyphs = it->pixel_width;
+      Lisp_Object charset_list = FRAME_TERMINAL (it->f)->charset_list;
 
-      if (it->glyph_row)
-       append_glyph (it);
+      if (char_charset (it->char_to_display, charset_list, NULL))
+       {
+         it->pixel_width = CHAR_WIDTH (it->char_to_display);
+         it->nglyphs = it->pixel_width;
+         if (it->glyph_row)
+           append_glyph (it);
+       }
+      else
+       {
+         Lisp_Object acronym = lookup_glyphless_char_display (-1, it);
+
+         xassert (it->what == IT_GLYPHLESS);
+         produce_glyphless_glyph (it, 1, acronym);
+       }
     }
 
  done:
@@ -1844,6 +1863,161 @@ produce_composite_glyph (struct it *it)
 }
 
 
+/* Append a glyph for a glyphless character to IT->glyph_row.  FACE_ID
+   is a face ID to be used for the glyph.  What actually appended are
+   glyphs of type CHAR_GLYPH of which characters are in STR
+   (it->nglyphs bytes).  */
+
+static void
+append_glyphless_glyph (struct it *it, int face_id, char *str)
+{
+  struct glyph *glyph, *end;
+  bidi_type_t bidi_type;
+  int resolved_level;
+  int i;
+
+  xassert (it->glyph_row);
+  glyph = it->glyph_row->glyphs[it->area] + it->glyph_row->used[it->area];
+  end = it->glyph_row->glyphs[1 + it->area];
+
+  /* If the glyph row is reversed, we need to prepend the glyph rather
+     than append it.  */
+  if (it->glyph_row->reversed_p && it->area == TEXT_AREA)
+    {
+      struct glyph *g;
+      int move_by = it->pixel_width;
+
+      /* Make room for the new glyphs.  */
+      if (move_by > end - glyph) /* don't overstep end of this area */
+       move_by = end - glyph;
+      for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
+       g[move_by] = *g;
+      glyph = it->glyph_row->glyphs[it->area];
+      end = glyph + move_by;
+    }
+
+  if (glyph >= end)
+    return;
+  glyph->type = CHAR_GLYPH;
+  glyph->pixel_width = 1;
+  glyph->face_id = face_id;
+  glyph->padding_p = 0;
+  glyph->charpos = CHARPOS (it->position);
+  glyph->object = it->object;
+  if (it->bidi_p)
+    {
+      glyph->resolved_level = it->bidi_it.resolved_level;
+      if ((it->bidi_it.type & 7) != it->bidi_it.type)
+       abort ();
+      glyph->bidi_type = it->bidi_it.type;
+    }
+  else
+    {
+      glyph->resolved_level = 0;
+      glyph->bidi_type = UNKNOWN_BT;
+    }
+
+  /* BIDI Note: we put the glyphs of characters left to right, even in
+     the REVERSED_P case because we write to the terminal
+     left-to-right.  */
+  for (i = 0; i < it->nglyphs && glyph < end; ++i)
+    {
+      if (i > 0)
+       glyph[0] = glyph[-1];
+      glyph->u.ch = str[i];
+      ++it->glyph_row->used[it->area];
+      ++glyph;
+    }
+}
+
+/* Declared in xdisp.c */
+extern struct frame *last_glyphless_glyph_frame;
+extern unsigned last_glyphless_glyph_face_id;
+extern int last_glyphless_glyph_merged_face_id;
+extern Lisp_Object Qglyphless_char;
+
+/* Produce glyphs for a glyphless character for iterator IT.
+   IT->glyphless_method specifies which method to use for displaying
+   the character.  See the description of enum
+   glyphless_display_method in dispextern.h for the detail.
+
+   FOR_NO_FONT is nonzero if and only if this is for a character that
+   is not supproted by the coding system of the terminal.  ACRONYM, if
+   non-nil, is an acronym string for the character.
+
+   The glyphs actually produced are of type CHAR_GLYPH.  */
+
+static void
+produce_glyphless_glyph (struct it *it, int for_no_font, Lisp_Object acronym)
+{
+  int face_id;
+  struct face *face;
+  int width, len;
+  char buf[9], *str = "    ";
+
+  /* Get a face ID for the glyph by utilizing a cache (the same way as
+     doen for `escape-glyph' in get_next_display_element).  */
+  if (it->f == last_glyphless_glyph_frame
+      && it->face_id == last_glyphless_glyph_face_id)
+    {
+      face_id = last_glyphless_glyph_merged_face_id;
+    }
+  else
+    {
+      /* Merge the `glyphless-char' face into the current face.  */
+      face_id = merge_faces (it->f, Qglyphless_char, 0, it->face_id);
+      last_glyphless_glyph_frame = it->f;
+      last_glyphless_glyph_face_id = it->face_id;
+      last_glyphless_glyph_merged_face_id = face_id;
+    }
+
+  if (it->glyphless_method == GLYPHLESS_DISPLAY_THIN_SPACE)
+    {
+      /* As there's no way to produce a thin space, we produce
+        a space of canonical width..  */
+      len = 1;
+    }
+  else if (it->glyphless_method == GLYPHLESS_DISPLAY_EMPTY_BOX)
+    {
+      len = CHAR_WIDTH (it->c);
+      if (len == 0)
+       len = 1;
+      else if (width > 4)
+       len = 4;
+    }
+  else
+    {
+      if (it->glyphless_method == GLYPHLESS_DISPLAY_ACRONYM)
+       {
+         int i;
+
+         if (! STRINGP (acronym) && CHAR_TABLE_P (Vglyphless_char_display))
+           acronym = CHAR_TABLE_REF (Vglyphless_char_display, it->c);
+         buf[0] = '[';
+         str = STRINGP (acronym) ? (char *) SDATA (acronym) : "";
+         for (len = 0; len < 6 && str[len] && ASCII_BYTE_P (str[len]); len++)
+           buf[1 + len] = str[len];
+         buf[1 + len] = ']';
+         len += 2;
+       }
+      else
+       {
+         xassert (it->glyphless_method == GLYPHLESS_DISPLAY_HEXA_CODE);
+         len = (it->c < 0x100 ? sprintf (buf, "U+%02X", it->c)
+                : it->c < 0x10000 ? sprintf (buf, "U+%04X", it->c)
+                : it->c <= MAX_UNICODE_CHAR ? sprintf (buf, "U+%06X", it->c)
+                : sprintf (buf, "E+%06X", it->c));
+       }
+      str = buf;
+    }
+
+  it->pixel_width = len;
+  it->nglyphs = len;
+  if (len > 0 && it->glyph_row)
+    append_glyphless_glyph (it, face_id, str);
+}
+
+
 /* Get information about special display element WHAT in an
    environment described by IT.  WHAT is one of IT_TRUNCATION or
    IT_CONTINUATION.  Maybe produce glyphs for WHAT if IT has a
index b9358896bae1b20892970a4df385f4b576c60fc4..e71c1159f0c0f1ad61d2ae35be3aade648450acf 100644 (file)
@@ -328,6 +328,11 @@ struct terminal
   /* Parameter alist of this terminal.  */
   Lisp_Object param_alist;
 
+  /* List of charsets supported by the terminal.  It is set by
+     Fset_terminal_coding_system_internal along with
+     the member terminal_coding.  */
+  Lisp_Object charset_list;
+
   /* All fields before `next_terminal' should be Lisp_Object and are traced
      by the GC.  All fields afterwards are ignored by the GC.  */
 
index 52938417aacbe2be667c1953af2ed3d51811ce53..ad90d57865b7e0c93767d5c1ba8a87bb9e1d2089 100644 (file)
@@ -5754,7 +5754,7 @@ static int (* get_next_element[NUM_IT_METHODS]) (struct it *it) =
    get_next_display_element for each character element, and from
    x_produce_glyphs when no suitable font was found.  */
 
-static Lisp_Object
+Lisp_Object
 lookup_glyphless_char_display (int c, struct it *it)
 {
   Lisp_Object glyphless_method = Qnil;
@@ -5780,7 +5780,6 @@ lookup_glyphless_char_display (int c, struct it *it)
       /* This method can't be used for the no-font case.  */
       glyphless_method = Qempty_box;
     }
-  it->what = IT_GLYPHLESS;
   if (EQ (glyphless_method, Qthin_space))
     it->glyphless_method = GLYPHLESS_DISPLAY_THIN_SPACE;
   else if (EQ (glyphless_method, Qempty_box))
@@ -5795,6 +5794,7 @@ lookup_glyphless_char_display (int c, struct it *it)
       glyphless_method = Qnil;
       goto retry;
     }
+  it->what = IT_GLYPHLESS;
   return glyphless_method;
 }
 
@@ -5806,9 +5806,9 @@ static struct frame *last_escape_glyph_frame = NULL;
 static unsigned last_escape_glyph_face_id = (1 << FACE_ID_BITS);
 static int last_escape_glyph_merged_face_id = 0;
 
-static struct frame *last_glyphless_glyph_frame = NULL;
-static unsigned last_glyphless_glyph_face_id = (1 << FACE_ID_BITS);
-static int last_glyphless_glyph_merged_face_id = 0;
+struct frame *last_glyphless_glyph_frame = NULL;
+unsigned last_glyphless_glyph_face_id = (1 << FACE_ID_BITS);
+int last_glyphless_glyph_merged_face_id = 0;
 
 int
 get_next_display_element (struct it *it)
@@ -22329,8 +22329,8 @@ append_glyphless_glyph (struct it *it, int face_id, int for_no_font, int len,
 
 /* Produce a glyph for a glyphless character for iterator IT.
    IT->glyphless_method specifies which method to use for displaying
-   the glyph.  See the description of enum glyphless_display_method in
-   dispextern.h for the default of the display methods.
+   the character.  See the description of enum
+   glyphless_display_method in dispextern.h for the detail.
 
    FOR_NO_FONT is nonzero if and only if this is for a character for
    which no font was found.  ACRONYM, if non-nil, is an acronym string