aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKenichi Handa <[email protected]>2010-11-01 13:09:26 +0900
committerKenichi Handa <[email protected]>2010-11-01 13:09:26 +0900
commitb18fad6db4efeda274dcb36706a4146650570e6b (patch)
tree5534ead2ed9b34b021ac3e92c88cf70350f26351
parent0269bd906626243b117136d6ea9eb98d2947b9f8 (diff)
Handle glyphless characters on tty.
-rw-r--r--lisp/ChangeLog4
-rw-r--r--lisp/faces.el4
-rw-r--r--src/ChangeLog18
-rw-r--r--src/coding.c7
-rw-r--r--src/dispextern.h2
-rw-r--r--src/term.c182
-rw-r--r--src/termhooks.h5
-rw-r--r--src/xdisp.c14
8 files changed, 222 insertions, 14 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 46160f878b..5d2e442a1c 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,7 @@
+2010-11-01 Kenichi Handa <[email protected]>
+
+ * faces.el (glyphless-char): Inherit underline for tty.
+
2010-10-28 Kenichi Handa <[email protected]>
Implement various display methods for glyphless characters.
diff --git a/lisp/faces.el b/lisp/faces.el
index 562bde6ed4..5e421f3f70 100644
--- a/lisp/faces.el
+++ b/lisp/faces.el
@@ -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"
diff --git a/src/ChangeLog b/src/ChangeLog
index eecad1f968..2d1ed5a96f 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,21 @@
+2010-11-01 Kenichi Handa <[email protected]>
+
+ * 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 <[email protected]>
* w32gui.h (STORE_XCHAR2B, XCHAR2B_BYTE1, XCHAR2B_BYTE2): Surround
diff --git a/src/coding.c b/src/coding.c
index 7a3bc40b9c..59deb22a3d 100644
--- a/src/coding.c
+++ b/src/coding.c
@@ -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;
}
diff --git a/src/dispextern.h b/src/dispextern.h
index af09ec5d3d..c2eeb6ec52 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -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 *);
diff --git a/src/term.c b/src/term.c
index 4baea231de..7593f02e60 100644
--- a/src/term.c
+++ b/src/term.c
@@ -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
diff --git a/src/termhooks.h b/src/termhooks.h
index b9358896ba..e71c1159f0 100644
--- a/src/termhooks.h
+++ b/src/termhooks.h
@@ -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. */
diff --git a/src/xdisp.c b/src/xdisp.c
index 52938417aa..ad90d57865 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -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