aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorKenichi Handa2010-11-01 13:09:26 +0900
committerKenichi Handa2010-11-01 13:09:26 +0900
commitb18fad6db4efeda274dcb36706a4146650570e6b (patch)
tree5534ead2ed9b34b021ac3e92c88cf70350f26351 /src
parent0269bd906626243b117136d6ea9eb98d2947b9f8 (diff)
downloademacs-b18fad6db4efeda274dcb36706a4146650570e6b.tar.gz
emacs-b18fad6db4efeda274dcb36706a4146650570e6b.zip
Handle glyphless characters on tty.
Diffstat (limited to 'src')
-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
6 files changed, 215 insertions, 13 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index eecad1f9689..2d1ed5a96fb 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,21 @@
12010-11-01 Kenichi Handa <handa@m17n.org>
2
3 * dispextern.h (lookup_glyphless_char_display): Extern it.
4
5 * termhooks.h (struct terminal): New member charset_list.
6
7 * coding.c (Fset_terminal_coding_system_internal): Set the
8 `charset_list' member of struct terminal.
9
10 * term.c (produce_glyphs): Handle the case it->what ==
11 IT_GLYPHLESS.
12 (append_glyphless_glyph, produce_glyphless_glyph): New functions.
13
14 * xdisp.c (lookup_glyphless_char_display): Make it non-static.
15 (lookup_glyphless_char_display): Set it->what at the end.
16 (last_glyphless_glyph_frame, last_glyphless_glyph_face_id)
17 (last_glyphless_glyph_merged_face_id): Make them non-static.
18
12010-10-29 Kenichi Handa <handa@m17n.org> 192010-10-29 Kenichi Handa <handa@m17n.org>
2 20
3 * w32gui.h (STORE_XCHAR2B, XCHAR2B_BYTE1, XCHAR2B_BYTE2): Surround 21 * w32gui.h (STORE_XCHAR2B, XCHAR2B_BYTE1, XCHAR2B_BYTE2): Surround
diff --git a/src/coding.c b/src/coding.c
index 7a3bc40b9c7..59deb22a3d7 100644
--- a/src/coding.c
+++ b/src/coding.c
@@ -9297,7 +9297,8 @@ DEFUN ("set-terminal-coding-system-internal", Fset_terminal_coding_system_intern
9297 doc: /* Internal use only. */) 9297 doc: /* Internal use only. */)
9298 (Lisp_Object coding_system, Lisp_Object terminal) 9298 (Lisp_Object coding_system, Lisp_Object terminal)
9299{ 9299{
9300 struct coding_system *terminal_coding = TERMINAL_TERMINAL_CODING (get_terminal (terminal, 1)); 9300 struct terminal *term = get_terminal (terminal, 1);
9301 struct coding_system *terminal_coding = TERMINAL_TERMINAL_CODING (term);
9301 CHECK_SYMBOL (coding_system); 9302 CHECK_SYMBOL (coding_system);
9302 setup_coding_system (Fcheck_coding_system (coding_system), terminal_coding); 9303 setup_coding_system (Fcheck_coding_system (coding_system), terminal_coding);
9303 /* We had better not send unsafe characters to terminal. */ 9304 /* We had better not send unsafe characters to terminal. */
@@ -9306,6 +9307,10 @@ DEFUN ("set-terminal-coding-system-internal", Fset_terminal_coding_system_intern
9306 terminal_coding->common_flags &= ~CODING_ANNOTATE_COMPOSITION_MASK; 9307 terminal_coding->common_flags &= ~CODING_ANNOTATE_COMPOSITION_MASK;
9307 terminal_coding->src_multibyte = 1; 9308 terminal_coding->src_multibyte = 1;
9308 terminal_coding->dst_multibyte = 0; 9309 terminal_coding->dst_multibyte = 0;
9310 if (terminal_coding->common_flags & CODING_REQUIRE_ENCODING_MASK)
9311 term->charset_list = coding_charset_list (terminal_coding);
9312 else
9313 term->charset_list = Fcons (Qascii, Qnil);
9309 return Qnil; 9314 return Qnil;
9310} 9315}
9311 9316
diff --git a/src/dispextern.h b/src/dispextern.h
index af09ec5d3de..c2eeb6ec527 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -3021,7 +3021,7 @@ extern EMACS_INT underline_minimum_offset;
3021extern Lisp_Object Vglyphless_char_display; 3021extern Lisp_Object Vglyphless_char_display;
3022 3022
3023extern void reseat_at_previous_visible_line_start (struct it *); 3023extern void reseat_at_previous_visible_line_start (struct it *);
3024 3024extern Lisp_Object lookup_glyphless_char_display (int, struct it *);
3025extern int calc_pixel_width_or_height (double *, struct it *, Lisp_Object, 3025extern int calc_pixel_width_or_height (double *, struct it *, Lisp_Object,
3026 struct font *, int, int *); 3026 struct font *, int, int *);
3027 3027
diff --git a/src/term.c b/src/term.c
index 4baea231de3..7593f02e607 100644
--- a/src/term.c
+++ b/src/term.c
@@ -1501,6 +1501,8 @@ static void append_glyph (struct it *);
1501static void produce_stretch_glyph (struct it *); 1501static void produce_stretch_glyph (struct it *);
1502static void append_composite_glyph (struct it *); 1502static void append_composite_glyph (struct it *);
1503static void produce_composite_glyph (struct it *); 1503static void produce_composite_glyph (struct it *);
1504static void append_glyphless_glyph (struct it *, int, char *);
1505static void produce_glyphless_glyph (struct it *, int, Lisp_Object);
1504 1506
1505/* Append glyphs to IT's glyph_row. Called from produce_glyphs for 1507/* Append glyphs to IT's glyph_row. Called from produce_glyphs for
1506 terminal frames if IT->glyph_row != NULL. IT->char_to_display is 1508 terminal frames if IT->glyph_row != NULL. IT->char_to_display is
@@ -1609,6 +1611,12 @@ produce_glyphs (struct it *it)
1609 goto done; 1611 goto done;
1610 } 1612 }
1611 1613
1614 if (it->what == IT_GLYPHLESS)
1615 {
1616 produce_glyphless_glyph (it, 0, Qnil);
1617 goto done;
1618 }
1619
1612 if (it->char_to_display >= 040 && it->char_to_display < 0177) 1620 if (it->char_to_display >= 040 && it->char_to_display < 0177)
1613 { 1621 {
1614 it->pixel_width = it->nglyphs = 1; 1622 it->pixel_width = it->nglyphs = 1;
@@ -1660,11 +1668,22 @@ produce_glyphs (struct it *it)
1660 } 1668 }
1661 else 1669 else
1662 { 1670 {
1663 it->pixel_width = CHAR_WIDTH (it->char_to_display); 1671 Lisp_Object charset_list = FRAME_TERMINAL (it->f)->charset_list;
1664 it->nglyphs = it->pixel_width;
1665 1672
1666 if (it->glyph_row) 1673 if (char_charset (it->char_to_display, charset_list, NULL))
1667 append_glyph (it); 1674 {
1675 it->pixel_width = CHAR_WIDTH (it->char_to_display);
1676 it->nglyphs = it->pixel_width;
1677 if (it->glyph_row)
1678 append_glyph (it);
1679 }
1680 else
1681 {
1682 Lisp_Object acronym = lookup_glyphless_char_display (-1, it);
1683
1684 xassert (it->what == IT_GLYPHLESS);
1685 produce_glyphless_glyph (it, 1, acronym);
1686 }
1668 } 1687 }
1669 1688
1670 done: 1689 done:
@@ -1844,6 +1863,161 @@ produce_composite_glyph (struct it *it)
1844} 1863}
1845 1864
1846 1865
1866/* Append a glyph for a glyphless character to IT->glyph_row. FACE_ID
1867 is a face ID to be used for the glyph. What actually appended are
1868 glyphs of type CHAR_GLYPH of which characters are in STR
1869 (it->nglyphs bytes). */
1870
1871static void
1872append_glyphless_glyph (struct it *it, int face_id, char *str)
1873{
1874 struct glyph *glyph, *end;
1875 bidi_type_t bidi_type;
1876 int resolved_level;
1877 int i;
1878
1879 xassert (it->glyph_row);
1880 glyph = it->glyph_row->glyphs[it->area] + it->glyph_row->used[it->area];
1881 end = it->glyph_row->glyphs[1 + it->area];
1882
1883 /* If the glyph row is reversed, we need to prepend the glyph rather
1884 than append it. */
1885 if (it->glyph_row->reversed_p && it->area == TEXT_AREA)
1886 {
1887 struct glyph *g;
1888 int move_by = it->pixel_width;
1889
1890 /* Make room for the new glyphs. */
1891 if (move_by > end - glyph) /* don't overstep end of this area */
1892 move_by = end - glyph;
1893 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
1894 g[move_by] = *g;
1895 glyph = it->glyph_row->glyphs[it->area];
1896 end = glyph + move_by;
1897 }
1898
1899 if (glyph >= end)
1900 return;
1901 glyph->type = CHAR_GLYPH;
1902 glyph->pixel_width = 1;
1903 glyph->face_id = face_id;
1904 glyph->padding_p = 0;
1905 glyph->charpos = CHARPOS (it->position);
1906 glyph->object = it->object;
1907 if (it->bidi_p)
1908 {
1909 glyph->resolved_level = it->bidi_it.resolved_level;
1910 if ((it->bidi_it.type & 7) != it->bidi_it.type)
1911 abort ();
1912 glyph->bidi_type = it->bidi_it.type;
1913 }
1914 else
1915 {
1916 glyph->resolved_level = 0;
1917 glyph->bidi_type = UNKNOWN_BT;
1918 }
1919
1920 /* BIDI Note: we put the glyphs of characters left to right, even in
1921 the REVERSED_P case because we write to the terminal
1922 left-to-right. */
1923 for (i = 0; i < it->nglyphs && glyph < end; ++i)
1924 {
1925 if (i > 0)
1926 glyph[0] = glyph[-1];
1927 glyph->u.ch = str[i];
1928 ++it->glyph_row->used[it->area];
1929 ++glyph;
1930 }
1931}
1932
1933/* Declared in xdisp.c */
1934extern struct frame *last_glyphless_glyph_frame;
1935extern unsigned last_glyphless_glyph_face_id;
1936extern int last_glyphless_glyph_merged_face_id;
1937extern Lisp_Object Qglyphless_char;
1938
1939/* Produce glyphs for a glyphless character for iterator IT.
1940 IT->glyphless_method specifies which method to use for displaying
1941 the character. See the description of enum
1942 glyphless_display_method in dispextern.h for the detail.
1943
1944 FOR_NO_FONT is nonzero if and only if this is for a character that
1945 is not supproted by the coding system of the terminal. ACRONYM, if
1946 non-nil, is an acronym string for the character.
1947
1948 The glyphs actually produced are of type CHAR_GLYPH. */
1949
1950static void
1951produce_glyphless_glyph (struct it *it, int for_no_font, Lisp_Object acronym)
1952{
1953 int face_id;
1954 struct face *face;
1955 int width, len;
1956 char buf[9], *str = " ";
1957
1958 /* Get a face ID for the glyph by utilizing a cache (the same way as
1959 doen for `escape-glyph' in get_next_display_element). */
1960 if (it->f == last_glyphless_glyph_frame
1961 && it->face_id == last_glyphless_glyph_face_id)
1962 {
1963 face_id = last_glyphless_glyph_merged_face_id;
1964 }
1965 else
1966 {
1967 /* Merge the `glyphless-char' face into the current face. */
1968 face_id = merge_faces (it->f, Qglyphless_char, 0, it->face_id);
1969 last_glyphless_glyph_frame = it->f;
1970 last_glyphless_glyph_face_id = it->face_id;
1971 last_glyphless_glyph_merged_face_id = face_id;
1972 }
1973
1974 if (it->glyphless_method == GLYPHLESS_DISPLAY_THIN_SPACE)
1975 {
1976 /* As there's no way to produce a thin space, we produce
1977 a space of canonical width.. */
1978 len = 1;
1979 }
1980 else if (it->glyphless_method == GLYPHLESS_DISPLAY_EMPTY_BOX)
1981 {
1982 len = CHAR_WIDTH (it->c);
1983 if (len == 0)
1984 len = 1;
1985 else if (width > 4)
1986 len = 4;
1987 }
1988 else
1989 {
1990 if (it->glyphless_method == GLYPHLESS_DISPLAY_ACRONYM)
1991 {
1992 int i;
1993
1994 if (! STRINGP (acronym) && CHAR_TABLE_P (Vglyphless_char_display))
1995 acronym = CHAR_TABLE_REF (Vglyphless_char_display, it->c);
1996 buf[0] = '[';
1997 str = STRINGP (acronym) ? (char *) SDATA (acronym) : "";
1998 for (len = 0; len < 6 && str[len] && ASCII_BYTE_P (str[len]); len++)
1999 buf[1 + len] = str[len];
2000 buf[1 + len] = ']';
2001 len += 2;
2002 }
2003 else
2004 {
2005 xassert (it->glyphless_method == GLYPHLESS_DISPLAY_HEXA_CODE);
2006 len = (it->c < 0x100 ? sprintf (buf, "U+%02X", it->c)
2007 : it->c < 0x10000 ? sprintf (buf, "U+%04X", it->c)
2008 : it->c <= MAX_UNICODE_CHAR ? sprintf (buf, "U+%06X", it->c)
2009 : sprintf (buf, "E+%06X", it->c));
2010 }
2011 str = buf;
2012 }
2013
2014 it->pixel_width = len;
2015 it->nglyphs = len;
2016 if (len > 0 && it->glyph_row)
2017 append_glyphless_glyph (it, face_id, str);
2018}
2019
2020
1847/* Get information about special display element WHAT in an 2021/* Get information about special display element WHAT in an
1848 environment described by IT. WHAT is one of IT_TRUNCATION or 2022 environment described by IT. WHAT is one of IT_TRUNCATION or
1849 IT_CONTINUATION. Maybe produce glyphs for WHAT if IT has a 2023 IT_CONTINUATION. Maybe produce glyphs for WHAT if IT has a
diff --git a/src/termhooks.h b/src/termhooks.h
index b9358896bae..e71c1159f0c 100644
--- a/src/termhooks.h
+++ b/src/termhooks.h
@@ -328,6 +328,11 @@ struct terminal
328 /* Parameter alist of this terminal. */ 328 /* Parameter alist of this terminal. */
329 Lisp_Object param_alist; 329 Lisp_Object param_alist;
330 330
331 /* List of charsets supported by the terminal. It is set by
332 Fset_terminal_coding_system_internal along with
333 the member terminal_coding. */
334 Lisp_Object charset_list;
335
331 /* All fields before `next_terminal' should be Lisp_Object and are traced 336 /* All fields before `next_terminal' should be Lisp_Object and are traced
332 by the GC. All fields afterwards are ignored by the GC. */ 337 by the GC. All fields afterwards are ignored by the GC. */
333 338
diff --git a/src/xdisp.c b/src/xdisp.c
index 52938417aac..ad90d57865b 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -5754,7 +5754,7 @@ static int (* get_next_element[NUM_IT_METHODS]) (struct it *it) =
5754 get_next_display_element for each character element, and from 5754 get_next_display_element for each character element, and from
5755 x_produce_glyphs when no suitable font was found. */ 5755 x_produce_glyphs when no suitable font was found. */
5756 5756
5757static Lisp_Object 5757Lisp_Object
5758lookup_glyphless_char_display (int c, struct it *it) 5758lookup_glyphless_char_display (int c, struct it *it)
5759{ 5759{
5760 Lisp_Object glyphless_method = Qnil; 5760 Lisp_Object glyphless_method = Qnil;
@@ -5780,7 +5780,6 @@ lookup_glyphless_char_display (int c, struct it *it)
5780 /* This method can't be used for the no-font case. */ 5780 /* This method can't be used for the no-font case. */
5781 glyphless_method = Qempty_box; 5781 glyphless_method = Qempty_box;
5782 } 5782 }
5783 it->what = IT_GLYPHLESS;
5784 if (EQ (glyphless_method, Qthin_space)) 5783 if (EQ (glyphless_method, Qthin_space))
5785 it->glyphless_method = GLYPHLESS_DISPLAY_THIN_SPACE; 5784 it->glyphless_method = GLYPHLESS_DISPLAY_THIN_SPACE;
5786 else if (EQ (glyphless_method, Qempty_box)) 5785 else if (EQ (glyphless_method, Qempty_box))
@@ -5795,6 +5794,7 @@ lookup_glyphless_char_display (int c, struct it *it)
5795 glyphless_method = Qnil; 5794 glyphless_method = Qnil;
5796 goto retry; 5795 goto retry;
5797 } 5796 }
5797 it->what = IT_GLYPHLESS;
5798 return glyphless_method; 5798 return glyphless_method;
5799} 5799}
5800 5800
@@ -5806,9 +5806,9 @@ static struct frame *last_escape_glyph_frame = NULL;
5806static unsigned last_escape_glyph_face_id = (1 << FACE_ID_BITS); 5806static unsigned last_escape_glyph_face_id = (1 << FACE_ID_BITS);
5807static int last_escape_glyph_merged_face_id = 0; 5807static int last_escape_glyph_merged_face_id = 0;
5808 5808
5809static struct frame *last_glyphless_glyph_frame = NULL; 5809struct frame *last_glyphless_glyph_frame = NULL;
5810static unsigned last_glyphless_glyph_face_id = (1 << FACE_ID_BITS); 5810unsigned last_glyphless_glyph_face_id = (1 << FACE_ID_BITS);
5811static int last_glyphless_glyph_merged_face_id = 0; 5811int last_glyphless_glyph_merged_face_id = 0;
5812 5812
5813int 5813int
5814get_next_display_element (struct it *it) 5814get_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,
22329 22329
22330/* Produce a glyph for a glyphless character for iterator IT. 22330/* Produce a glyph for a glyphless character for iterator IT.
22331 IT->glyphless_method specifies which method to use for displaying 22331 IT->glyphless_method specifies which method to use for displaying
22332 the glyph. See the description of enum glyphless_display_method in 22332 the character. See the description of enum
22333 dispextern.h for the default of the display methods. 22333 glyphless_display_method in dispextern.h for the detail.
22334 22334
22335 FOR_NO_FONT is nonzero if and only if this is for a character for 22335 FOR_NO_FONT is nonzero if and only if this is for a character for
22336 which no font was found. ACRONYM, if non-nil, is an acronym string 22336 which no font was found. ACRONYM, if non-nil, is an acronym string