Commit b18fad6d authored by Kenichi Handa's avatar Kenichi Handa

Handle glyphless characters on tty.

parent 0269bd90
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.
......
......@@ -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"
......
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
......
......@@ -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;
}
......
......@@ -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 *);
......
......@@ -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
......
......@@ -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. */
......
......@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment