1
0
mirror of https://git.savannah.gnu.org/git/emacs.git synced 2024-11-27 07:37:33 +00:00

Fix and document display of glyphless characters.

src/xdisp.c (set_cursor_from_row): Fix cursor positioning on
 zero-width characters.
 (syms_of_xdisp) <glyphless-char-display>: Doc fix.
 src/.gdbinit (pgx): Adapt to latest changes in `struct glyph'.
 src/w32term.c (x_draw_glyphless_glyph_string_foreground): Draw the
 box before drawing the glyphs inside it.
 src/dispextern.h (enum glyphless_display_method): Rename
 GLYPHLESS_DISPLAY_HEXA_CODE to GLYPHLESS_DISPLAY_HEX_CODE.  All
 users changed.
 src/term.c (append_glyphless_glyph, produce_glyphless_glyph): Fix
 comments.
 (produce_glyphless_glyph): Enclose "U+nnnn" and "empty box"
 whitespace in "[]", to simulate a box.  Don't use uninitialized
 variable `width'.
 lisp/international/characters.el (glyphless-char-display-control):
 Renamed from glyphless-char-control; all users changed.  Doc fix.
 Signal an error if display method is not one of the recognized
 symbols.
 doc/emacs/rmail.texi (Rmail Coding): Characters with no fonts are not
 necessarily displayed as empty boxes.
 doc/emacs/mule.texi (Language Environments, Fontsets): Characters with no
 fonts are not necessarily displayed as empty boxes.
 doc/emacs/display.texi (Text Display): Document display of glyphless
 characters.
 doc/lispref/display.texi (Usual Display): Characters with no fonts are not
 necessarily displayed as empty boxes.
 etc/NEWS: Document display of glyphless characters.
This commit is contained in:
Eli Zaretskii 2010-11-13 15:29:31 +02:00
parent 6e060cee81
commit 0eb025fb55
17 changed files with 214 additions and 82 deletions

View File

@ -1,3 +1,14 @@
2010-11-13 Eli Zaretskii <eliz@gnu.org>
* rmail.texi (Rmail Coding): Characters with no fonts are not
necessarily displayed as empty boxes.
* mule.texi (Language Environments, Fontsets): Characters with no
fonts are not necessarily displayed as empty boxes.
* display.texi (Text Display): Document display of glyphless
characters.
2010-11-13 Glenn Morris <rgm@gnu.org>
* basic.texi (Position Info): Add M-x count-words-region.

View File

@ -1136,6 +1136,48 @@ prefix these characters with an escape character.
by means of a display table. @xref{Display Tables,, Display Tables,
elisp, The Emacs Lisp Reference Manual}.
@cindex glyphless characters
@cindex characters with no font glyphs
On graphics displays, some characters could have no glyphs in any of
the fonts available to Emacs. On text terminals, some characters
could be impossible to encode with the terminal coding system
(@pxref{Terminal Coding}). Emacs can display such @dfn{glyphless}
characters using one of the following methods:
@table @code
@item zero-width
Don't display the character.
@item thin-space
Display a thin space, 1-pixel wide on graphics displays or 1-character
wide on text terminals.
@item empty-box
Display an empty box.
@item acronym
Display the acronym of the character's name (such as @sc{zwnj} or
@sc{rlm}) in a box.
@item hex-code
Display the Unicode codepoint of the character in hexadecimal
notation, in a box.
@end table
@noindent
@cindex @code{glyphless-char} face
With the exception of @code{zero-width}, all other methods draw these
characters in a special face @code{glyphless-char}, which you can
customize.
@vindex glyphless-char-display-control
@vindex char-acronym-table
To control what glyphless characters are displayed using which method,
customize the variable @code{glyphless-char-display-control}; see its
doc string for the details. For even finer control, set the elements
of 2 char-tables: @code{glyphless-char-display} and
@code{char-acronym-table}.
@node Cursor Display
@section Displaying the Cursor

View File

@ -351,10 +351,11 @@ which prefers Cyrillic characters and files encoded in Windows-1255).
@cindex Intlfonts package, installation
To display the script(s) used by your language environment on a
graphical display, you need to have a suitable font. If some of the
characters appear as empty boxes, you should install the GNU Intlfonts
package, which includes fonts for most supported scripts.@footnote{If
you run Emacs on X, you need to inform the X server about the location
of the newly installed fonts with the following commands:
characters appear as empty boxes or hex codes, you should install the
GNU Intlfonts package, which includes fonts for most supported
scripts.@footnote{If you run Emacs on X, you need to inform the X
server about the location of the newly installed fonts with the
following commands:
@example
xset fp+ /usr/local/share/emacs/fonts
@ -1314,10 +1315,11 @@ characters the font does not cover. The standard fontset is only used if
explicitly requested, despite its name.
A fontset does not necessarily specify a font for every character
code. If a fontset specifies no font for a certain character, or if it
specifies a font that does not exist on your system, then it cannot
display that character properly. It will display that character as an
empty box instead.
code. If a fontset specifies no font for a certain character, or if
it specifies a font that does not exist on your system, then it cannot
display that character properly. It will display that character as a
hex code or thin space or an empty box instead. (@xref{Text Display,
glyphless characters}, for details.)
@node Defining Fontsets
@section Defining fontsets

View File

@ -1192,7 +1192,8 @@ specification, or because the specification was inaccurate. For
example, a misconfigured mailer could send a message with a
@samp{charset=iso-8859-1} header when the message is actually encoded
in @code{koi8-r}. When you see the message text garbled, or some of
its characters displayed as empty boxes, this may have happened.
its characters displayed as hex codes or empty boxes, this may have
happened.
@findex rmail-redecode-body
You can correct the problem by decoding the message again using the

View File

@ -1,3 +1,8 @@
2010-11-13 Eli Zaretskii <eliz@gnu.org>
* display.texi (Usual Display): Characters with no fonts are not
necessarily displayed as empty boxes.
2010-10-31 Glenn Morris <rgm@gnu.org>
* maps.texi (Standard Keymaps): Update File menu description.

View File

@ -5579,9 +5579,9 @@ digit characters representing the character code in octal. (A display
table can specify a glyph to use instead of @samp{\}.)
@item
Multibyte character codes above 256 are displayed as themselves, or as a
question mark or empty box if the terminal cannot display that
character.
Multibyte character codes above 256 are displayed as themselves, or as
a question mark or a hex code or an empty box if the terminal cannot
display that character.
@end itemize
The usual display conventions apply even when there is a display

View File

@ -1,3 +1,7 @@
2010-11-13 Eli Zaretskii <eliz@gnu.org>
* NEWS: Document display of glyphless characters.
2010-11-11 Eric Schulte <schulte.eric@gmail.com>
* refcards/orgcard.tex: Add new Babel key sequences.

View File

@ -138,6 +138,18 @@ with Xft. To change font, use X resource faceName, for example:
Emacs.pane.menubar.faceName: Courier-12
Set faceName to none and use font to use the old X fonts.
+++
** Enhanced support for characters that have no glyphs in available fonts
If a character has no glyphs in any of the available fonts, Emacs by
default will display it either as a hexadecimal code in a box or as a
thin 1-pixel space. In addition to these two methods, Emacs can
display these characters as empty box, as an acronym, or not display
them at all. To change how these characters are displayed, customize
the variable `glyphless-char-display-control'.
On character terminals these methods are used for characters that
cannot be encoded by the `terminal-coding-system'.
** On graphical displays, the mode-line no longer ends in dashes.
** Basic SELinux support has been added.

View File

@ -1,3 +1,9 @@
2010-11-13 Eli Zaretskii <eliz@gnu.org>
* international/characters.el (glyphless-char-display-control):
Doc fix. Signal an error if display method is not one of the
recognized symbols.
2010-11-13 Michael Albinus <michael.albinus@gmx.de>
* net/tramp-compat.el (tramp-compat-line-beginning-position)

View File

@ -1294,40 +1294,48 @@ Setup char-width-table appropriate for non-CJK language environment."
(aset char-acronym-table #xE007F "->|TAG") ; CANCEL TAG
;;; Control of displaying glyphless characters.
(defvar glyphless-char-control
(defvar glyphless-char-display-control
'((format-control . thin-space)
(no-font . hexa-code))
"List of directives to control displaying of glyphless characters.
(no-font . hex-code))
"List of directives to control display of glyphless characters.
Each element has the form (TARGET . METHOD), where TARGET is a
symbol specifying the target character group to control, and
METHOD is a symbol specifying the method of displaying them.
Each element has the form (GROUP . METHOD), where GROUP is a
symbol specifying the character group, and METHOD is a symbol
specifying the method of displaying characters belonging to that
group.
TARGET must be one of these symbols:
GROUP must be one of these symbols:
`c0-control': U+0000..U+001F.
`c1-control': U+0080..U+009F.
`format-control': Characters of Unicode General Category `Cf'.
Ex: U+200C (ZWNJ), U+200E (LRM)), but don't include characters
that have graphic image such as U+00AD (SHY).
`format-control': Characters of Unicode General Category `Cf',
such as U+200C (ZWNJ), U+200E (LRM), but
excluding characters that have graphic images,
such as U+00AD (SHY).
`no-font': characters for which no suitable font is found.
For character terminals, characters that cannot
be encoded by `terminal-coding-system'.
METHOD must be one of these symbols:
`zero-width': don't display.
`thin-space': display a thin space (1-pixel width).
`thin-space': display a thin (1-pixel width) space. On character
terminals, display as 1-character space.
`empty-box': display an empty box.
`acronym': display an acronum string in a box.
`hexa-code': display a hexadecimal character code in a box.
`acronym': display an acronym of the character in a box. The
acronym is taken from `char-acronym-table', which see.
`hex-code': display the hexadecimal character code in a box.
Just setting this variable does not take effect. Call the
function `update-glyphless-char-display' (which see) after
setting this variable.")
(defun update-glyphless-char-display ()
"Make the setting of `glyphless-char-control' take effect.
"Make the setting of `glyphless-char-display-control' take effect.
This function updates the char-table `glyphless-char-display'."
(dolist (elt glyphless-char-control)
(dolist (elt glyphless-char-display-control)
(let ((target (car elt))
(method (cdr elt)))
(or (memq method '(zero-width thin-space empty-box acronym hex-code))
(error "Invalid glyphless character display method: %s" method))
(cond ((eq target 'c0-control)
(set-char-table-range glyphless-char-display '(#x00 . #x1F)
method))
@ -1355,7 +1363,7 @@ This function updates the char-table `glyphless-char-display'."
((eq target 'no-font)
(set-char-table-extra-slot glyphless-char-display 0 method))
(t
(error "Invalid target character group: %s" target))))))
(error "Invalid glyphless character group: %s" target))))))
(update-glyphless-char-display)

View File

@ -494,14 +494,30 @@ define pgx
end
# COMPOSITE_GLYPH
if ($g->type == 1)
printf "COMP[%d (%d..%d)]", $g->u.cmp.id, $g->u.cmp.from, $g->u.cmp.to
printf "COMP[%d (%d..%d)]", $g->u.cmp.id, $g->slice.cmp.from, $g->slice.cmp.to
end
# GLYPHLESS_GLYPH
if ($g->type == 2)
printf "GLYPHLESS["
if ($g->u.glyphless.method == 0)
printf "THIN]"
end
if ($g->u.glyphless.method == 1)
printf "EMPTY]"
end
if ($g->u.glyphless.method == 2)
printf "ACRO]"
end
if ($g->u.glyphless.method == 3)
printf "HEX]"
end
end
# IMAGE_GLYPH
if ($g->type == 2)
if ($g->type == 3)
printf "IMAGE[%d]", $g->u.img_id
end
# STRETCH_GLYPH
if ($g->type == 3)
if ($g->type == 4)
printf "STRETCH[%d+%d]", $g->u.stretch.height, $g->u.stretch.ascent
end
xgettype ($g->object)
@ -544,8 +560,8 @@ define pgx
if ($g->right_box_line_p)
printf " ]"
end
if ($g->slice.x || $g->slice.y || $g->slice.width || $g->slice.height)
printf " slice=%d,%d,%d,%d" ,$g->slice.x, $g->slice.y, $g->slice.width, $g->slice.height
if ($g->slice.img.x || $g->slice.img.y || $g->slice.img.width || $g->slice.img.height)
printf " slice=%d,%d,%d,%d" ,$g->slice.img.x, $g->slice.img.y, $g->slice.img.width, $g->slice.img.height
end
printf "\n"
end

View File

@ -1,3 +1,25 @@
2010-11-13 Eli Zaretskii <eliz@gnu.org>
* xdisp.c (set_cursor_from_row): Fix cursor positioning on
zero-width characters.
* .gdbinit (pgx): Adapt to latest changes in `struct glyph'.
* w32term.c (x_draw_glyphless_glyph_string_foreground): Draw the
box before drawing the glyphs inside it.
* xdisp.c (syms_of_xdisp) <glyphless-char-display>: Doc fix.
* dispextern.h (enum glyphless_display_method): Rename
GLYPHLESS_DISPLAY_HEXA_CODE to GLYPHLESS_DISPLAY_HEX_CODE. All
users changed.
* term.c (append_glyphless_glyph, produce_glyphless_glyph): Fix
comments.
(produce_glyphless_glyph): Enclose "U+nnnn" and "empty box"
whitespace in "[]", to simulate a box. Don't use uninitialized
variable `width'.
2010-11-11 Julien Danjou <julien@danjou.info>
* xsettings.c (init_xsettings): Use already fetch atoms.

View File

@ -371,12 +371,11 @@ struct glyph
displaying. The member `pixel_width' above is set to 1. */
unsigned padding_p : 1;
/* 1 means the actual glyph is not available, draw a box instead.
This can happen when a font couldn't be loaded, or a character
doesn't have a glyph in a font. */
/* 1 means the actual glyph is not available, draw using `struct
glyphless' below instead. This can happen when a font couldn't
be loaded, or a character doesn't have a glyph in a font. */
unsigned glyph_not_available_p : 1;
/* Non-zero means don't display cursor here. */
unsigned avoid_cursor_p : 1;
@ -1997,14 +1996,15 @@ enum line_wrap_method
enum glyphless_display_method
{
/* Display a thin (1-pixel width) space. */
/* Display a thin (1-pixel width) space. On a TTY, display a
1-character width space. */
GLYPHLESS_DISPLAY_THIN_SPACE,
/* Display an empty box of proper width. */
GLYPHLESS_DISPLAY_EMPTY_BOX,
/* Display an acronym string in a box. */
GLYPHLESS_DISPLAY_ACRONYM,
/* Display a hexadecimal character code in a box. */
GLYPHLESS_DISPLAY_HEXA_CODE
/* Display the hexadecimal code of the character in a box. */
GLYPHLESS_DISPLAY_HEX_CODE
};
struct it_slice

View File

@ -1850,9 +1850,9 @@ 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). */
is a face ID to be used for the glyph. What is actually appended
are glyphs of type CHAR_GLYPH whose characters are in STR (which
comes from it->nglyphs bytes). */
static void
append_glyphless_glyph (struct it *it, int face_id, char *str)
@ -1923,7 +1923,7 @@ 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.
glyphless_display_method in dispextern.h for the details.
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
@ -1935,11 +1935,11 @@ static void
produce_glyphless_glyph (struct it *it, int for_no_font, Lisp_Object acronym)
{
int face_id;
int width, len;
char buf[9], *str = " ";
int len;
char buf[11], *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). */
done for `escape-glyph' in get_next_display_element). */
if (it->f == last_glyphless_glyph_frame
&& it->face_id == last_glyphless_glyph_face_id)
{
@ -1956,8 +1956,8 @@ produce_glyphless_glyph (struct it *it, int for_no_font, Lisp_Object acronym)
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.. */
/* 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)
@ -1965,8 +1965,11 @@ produce_glyphless_glyph (struct it *it, int for_no_font, Lisp_Object acronym)
len = CHAR_WIDTH (it->c);
if (len == 0)
len = 1;
else if (width > 4)
else if (len > 4)
len = 4;
sprintf (buf, "[%.*s]", len, str);
len += 2;
str = buf;
}
else
{
@ -1983,11 +1986,11 @@ produce_glyphless_glyph (struct it *it, int for_no_font, Lisp_Object acronym)
}
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));
xassert (it->glyphless_method == GLYPHLESS_DISPLAY_HEX_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;
}

View File

@ -1440,7 +1440,7 @@ x_draw_glyphless_glyph_string_foreground (struct glyph_string *s)
str = (char *) SDATA (acronym);
}
}
else if (glyph->u.glyphless.method == GLYPHLESS_DISPLAY_HEXA_CODE)
else if (glyph->u.glyphless.method == GLYPHLESS_DISPLAY_HEX_CODE)
{
sprintf ((char *) buf, "%0*X",
glyph->u.glyphless.ch < 0x10000 ? 4 : 6,
@ -1448,6 +1448,11 @@ x_draw_glyphless_glyph_string_foreground (struct glyph_string *s)
str = buf;
}
if (glyph->u.glyphless.method != GLYPHLESS_DISPLAY_THIN_SPACE)
w32_draw_rectangle (s->hdc, s->gc,
x, s->ybase - glyph->ascent,
glyph->pixel_width - 1,
glyph->ascent + glyph->descent - 1);
if (str)
{
struct font *font = s->font;
@ -1456,7 +1461,7 @@ x_draw_glyphless_glyph_string_foreground (struct glyph_string *s)
HFONT old_font;
old_font = SelectObject (s->hdc, FONT_HANDLE (font));
/* It is assured that all LEN characters in STR is ASCII. */
/* It is certain that all LEN characters in STR are ASCII. */
for (j = 0; j < len; j++)
{
code = font->driver->encode_char (font, str[j]);
@ -1472,11 +1477,6 @@ x_draw_glyphless_glyph_string_foreground (struct glyph_string *s)
with_background);
SelectObject (s->hdc, old_font);
}
if (glyph->u.glyphless.method != GLYPHLESS_DISPLAY_THIN_SPACE)
w32_draw_rectangle (s->hdc, s->gc,
x, s->ybase - glyph->ascent,
glyph->pixel_width - 1,
glyph->ascent + glyph->descent - 1);
x += glyph->pixel_width;
}
}

View File

@ -971,7 +971,7 @@ Lisp_Object Vglyphless_char_display;
Lisp_Object Qglyphless_char_display;
/* Method symbols for Vglyphless_char_display. */
static Lisp_Object Qhexa_code, Qempty_box, Qthin_space, Qzero_width;
static Lisp_Object Qhex_code, Qempty_box, Qthin_space, Qzero_width;
/* Default pixel width of `thin-space' display method. */
#define THIN_SPACE_WIDTH 1
@ -5813,8 +5813,8 @@ lookup_glyphless_char_display (int c, struct it *it)
it->glyphless_method = GLYPHLESS_DISPLAY_THIN_SPACE;
else if (EQ (glyphless_method, Qempty_box))
it->glyphless_method = GLYPHLESS_DISPLAY_EMPTY_BOX;
else if (EQ (glyphless_method, Qhexa_code))
it->glyphless_method = GLYPHLESS_DISPLAY_HEXA_CODE;
else if (EQ (glyphless_method, Qhex_code))
it->glyphless_method = GLYPHLESS_DISPLAY_HEX_CODE;
else if (STRINGP (glyphless_method))
it->glyphless_method = GLYPHLESS_DISPLAY_ACRONYM;
else
@ -12871,10 +12871,10 @@ set_cursor_from_row (struct window *w, struct glyph_row *row,
|| (row->truncated_on_left_p && pt_old < bpos_min)
|| (row->truncated_on_right_p && pt_old > bpos_max)
/* Zero-width characters produce no glyphs. */
|| ((row->reversed_p
|| (!string_seen
&& (row->reversed_p
? glyph_after > glyphs_end
: glyph_after < glyphs_end)
&& eabs (glyph_after - glyph_before) == 1))
: glyph_after < glyphs_end)))
{
cursor = glyph_after;
x = -1;
@ -22292,7 +22292,7 @@ calc_line_height_property (struct it *it, Lisp_Object val, struct font *font,
and only if this is for a character for which no font was found.
If the display method (it->glyphless_method) is
GLYPHLESS_DISPLAY_ACRONYM or GLYPHLESS_DISPLAY_HEXA_CODE, LEN is a
GLYPHLESS_DISPLAY_ACRONYM or GLYPHLESS_DISPLAY_HEX_CODE, LEN is a
length of the acronym or the hexadecimal string, UPPER_XOFF and
UPPER_YOFF are pixel offsets for the upper part of the string,
LOWER_XOFF and LOWER_YOFF are for the lower part.
@ -22441,7 +22441,7 @@ produce_glyphless_glyph (struct it *it, int for_no_font, Lisp_Object acronym)
}
else
{
xassert (it->glyphless_method == GLYPHLESS_DISPLAY_HEXA_CODE);
xassert (it->glyphless_method == GLYPHLESS_DISPLAY_HEX_CODE);
sprintf (buf, "%0*X", it->c < 0x10000 ? 4 : 6, it->c);
str = buf;
}
@ -27057,7 +27057,7 @@ cursor shapes. */);
hourglass_shown_p = 0;
DEFSYM (Qglyphless_char, "glyphless-char");
DEFSYM (Qhexa_code, "hexa-code");
DEFSYM (Qhex_code, "hex-code");
DEFSYM (Qempty_box, "empty-box");
DEFSYM (Qthin_space, "thin-space");
DEFSYM (Qzero_width, "zero-width");
@ -27073,13 +27073,13 @@ cursor shapes. */);
doc: /* Char-table to control displaying of glyphless characters.
Each element, if non-nil, is an ASCII acronym string (displayed in a box)
or one of these symbols:
hexa-code: display with hexadecimal character code in a box
empty-box: display with an empty box
thin-space: display with 1-pixel width space
hex-code: display the hexadecimal code of a character in a box
empty-box: display as an empty box
thin-space: display as 1-pixel width space
zero-width: don't display
It has one extra slot to control the display of a character for which
no font is found. The value of the slot is `hexa-code' or `empty-box'.
no font is found. The value of the slot is `hex-code' or `empty-box'.
The default is `empty-box'. */);
Vglyphless_char_display = Fmake_char_table (Qglyphless_char_display, Qnil);
Fset_char_table_extra_slot (Vglyphless_char_display, make_number (0),

View File

@ -1369,7 +1369,7 @@ x_draw_glyphless_glyph_string_foreground (struct glyph_string *s)
str = (char *) SDATA (acronym);
}
}
else if (glyph->u.glyphless.method == GLYPHLESS_DISPLAY_HEXA_CODE)
else if (glyph->u.glyphless.method == GLYPHLESS_DISPLAY_HEX_CODE)
{
sprintf ((char *) buf, "%0*X",
glyph->u.glyphless.ch < 0x10000 ? 4 : 6,