Improvements for curved quotes on Linux consule
This should help Emacs work better out-of-the-box on Linux consoles, which have only limited support for displaying Unicode characters. Also, undo the recent change that caused text-quoting-style to affect quote display on terminals, so that the two features are independent. See Alan Mackenzie in: http://lists.gnu.org/archive/html/emacs-devel/2015-09/msg00244.html Finally, add a style parameter to startup--setup-quote-display, so that this function can also be invoked after startup, with different styles depending on user preference at the time. * configure.ac: Check for linux/kd.h header. * doc/emacs/display.texi (Text Display): Document quote display. * doc/lispref/display.texi (Active Display Table): * etc/NEWS: * lisp/startup.el (startup--setup-quote-display, command-line): text-quoting-style no longer affects quote display. * doc/lispref/frames.texi (Terminal Parameters): Fix typo. * lisp/international/mule-util.el (char-displayable-p): * lisp/startup.el (startup--setup-quote-display): On a text terminal supporting glyph codes, use the reported glyph codes instead of the terminal coding system, as this is more accurate on the Linux console. * lisp/startup.el (startup--setup-quote-display): New optional arg STYLE. * src/fontset.c (Finternal_char_font): Report glyph codes for a text terminal, if they are available. Currently this is supported only for the Linux console. * src/termhooks.h (struct terminal): New member glyph-code-table. * src/terminal.c [HAVE_LINUX_KD_H]: Include <errno.h>, <linux/kd.h>. (calculate_glyph_code_table) [HAVE_LINUX_KD_H]: New function. (terminal_glyph_code): New function.
This commit is contained in:
parent
39dca94701
commit
6e5d81ff45
10 changed files with 195 additions and 69 deletions
|
@ -1582,6 +1582,7 @@ fi
|
|||
|
||||
dnl checks for header files
|
||||
AC_CHECK_HEADERS_ONCE(
|
||||
linux/kd.h
|
||||
sys/systeminfo.h
|
||||
sys/sysinfo.h
|
||||
coff.h pty.h
|
||||
|
|
|
@ -1480,6 +1480,15 @@ customizing the variable @code{glyphless-char-display-control}.
|
|||
@xref{Glyphless Chars,, Glyphless Character Display, elisp, The Emacs
|
||||
Lisp Reference Manual}, for details.
|
||||
|
||||
@cindex curly quotes
|
||||
@cindex curved quotes
|
||||
@cindex escape-glyph face
|
||||
If the curved quotes @samp{‘}, @samp{’}, @samp{“}, and @samp{”} are
|
||||
known to look just like @acronym{ASCII} characters, they are shown
|
||||
with the @code{escape-glyph} face. Curved quotes that cannot be
|
||||
displayed are shown as their @acronym{ASCII} approximations @samp{`},
|
||||
@samp{'}, and @samp{"} with the @code{escape-glyph} face.
|
||||
|
||||
@node Cursor Display
|
||||
@section Displaying the Cursor
|
||||
@cindex text cursor
|
||||
|
|
|
@ -6533,10 +6533,8 @@ used when Emacs is displaying a buffer in a window with neither a
|
|||
window display table nor a buffer display table defined, or when Emacs
|
||||
is outputting text to the standard output or error streams. Although its
|
||||
default is typically @code{nil}, in an interactive session if the
|
||||
locale cannot display curved quotes, or if the initial value of
|
||||
@code{text-quoting-style} specifies a preference for ASCII, its
|
||||
default maps curved quotes to ASCII approximations. @xref{Keys in
|
||||
Documentation}.
|
||||
terminal cannot display curved quotes, its default maps curved quotes
|
||||
to ASCII approximations. @xref{Keys in Documentation}.
|
||||
@end defvar
|
||||
|
||||
The @file{disp-table} library defines several functions for changing
|
||||
|
|
|
@ -1781,7 +1781,7 @@ symbol) of @var{terminal}. If @var{terminal} has no setting for
|
|||
@end defun
|
||||
|
||||
@defun set-terminal-parameter terminal parameter value
|
||||
This function sets the parameter @var{parm} of @var{terminal} to the
|
||||
This function sets the parameter @var{parameter} of @var{terminal} to the
|
||||
specified @var{value}, and returns the previous value of that
|
||||
parameter.
|
||||
@end defun
|
||||
|
|
3
etc/NEWS
3
etc/NEWS
|
@ -1125,8 +1125,7 @@ integers.
|
|||
of the Emacs process to binary I/O mode.
|
||||
|
||||
** ASCII approximations to curved quotes are put in standard-display-table
|
||||
if the locale cannot display curved quotes, or if text-quoting-style
|
||||
initially specifies a preference for ASCII.
|
||||
if the terminal cannot display curved quotes.
|
||||
|
||||
** Standard output and error streams now transliterate characters via
|
||||
standard-display-table, and encode output using locale-coding-system.
|
||||
|
|
|
@ -273,43 +273,48 @@ per-character basis, this may not be accurate."
|
|||
((not enable-multibyte-characters)
|
||||
;; Maybe there's a font for it, but we can't put it in the buffer.
|
||||
nil)
|
||||
((display-multi-font-p)
|
||||
;; On a window system, a character is displayable if we have
|
||||
;; a font for that character in the default face of the
|
||||
;; currently selected frame.
|
||||
(car (internal-char-font nil char)))
|
||||
(t
|
||||
;; On a terminal, a character is displayable if the coding
|
||||
;; system for the terminal can encode it.
|
||||
(let ((coding (terminal-coding-system)))
|
||||
(when coding
|
||||
(let ((cs-list (coding-system-get coding :charset-list)))
|
||||
(cond
|
||||
((listp cs-list)
|
||||
(catch 'tag
|
||||
(mapc #'(lambda (charset)
|
||||
(if (encode-char char charset)
|
||||
(throw 'tag charset)))
|
||||
cs-list)
|
||||
nil))
|
||||
((eq cs-list 'iso-2022)
|
||||
(catch 'tag2
|
||||
(mapc #'(lambda (charset)
|
||||
(if (and (plist-get (charset-plist charset)
|
||||
:iso-final-char)
|
||||
(encode-char char charset))
|
||||
(throw 'tag2 charset)))
|
||||
charset-list)
|
||||
nil))
|
||||
((eq cs-list 'emacs-mule)
|
||||
(catch 'tag3
|
||||
(mapc #'(lambda (charset)
|
||||
(if (and (plist-get (charset-plist charset)
|
||||
:emacs-mule-id)
|
||||
(encode-char char charset))
|
||||
(throw 'tag3 charset)))
|
||||
charset-list)
|
||||
nil)))))))))
|
||||
(let ((font-glyph (internal-char-font nil char)))
|
||||
(if font-glyph
|
||||
(if (consp font-glyph)
|
||||
;; On a window system, a character is displayable
|
||||
;; if a font for that character is in the default
|
||||
;; face of the currently selected frame.
|
||||
(car font-glyph)
|
||||
;; On a text terminal supporting glyph codes, CHAR is
|
||||
;; displayable if its glyph code is nonnegative.
|
||||
(<= 0 font-glyph))
|
||||
;; On a teext terminal without glyph codes, CHAR is displayable
|
||||
;; if the coding system for the terminal can encode it.
|
||||
(let ((coding (terminal-coding-system)))
|
||||
(when coding
|
||||
(let ((cs-list (coding-system-get coding :charset-list)))
|
||||
(cond
|
||||
((listp cs-list)
|
||||
(catch 'tag
|
||||
(mapc #'(lambda (charset)
|
||||
(if (encode-char char charset)
|
||||
(throw 'tag charset)))
|
||||
cs-list)
|
||||
nil))
|
||||
((eq cs-list 'iso-2022)
|
||||
(catch 'tag2
|
||||
(mapc #'(lambda (charset)
|
||||
(if (and (plist-get (charset-plist charset)
|
||||
:iso-final-char)
|
||||
(encode-char char charset))
|
||||
(throw 'tag2 charset)))
|
||||
charset-list)
|
||||
nil))
|
||||
((eq cs-list 'emacs-mule)
|
||||
(catch 'tag3
|
||||
(mapc #'(lambda (charset)
|
||||
(if (and (plist-get (charset-plist charset)
|
||||
:emacs-mule-id)
|
||||
(encode-char char charset))
|
||||
(throw 'tag3 charset)))
|
||||
charset-list)
|
||||
nil)))))))))))
|
||||
|
||||
(defun filepos-to-bufferpos--dos (byte f)
|
||||
(let ((eol-offset 0)
|
||||
|
|
|
@ -803,19 +803,61 @@ to prepare for opening the first frame (e.g. open a connection to an X server)."
|
|||
(defvar server-name)
|
||||
(defvar server-process)
|
||||
|
||||
(defun startup--setup-quote-display ()
|
||||
"Display ASCII approximations on user request or if curved quotes don't work."
|
||||
(when (memq text-quoting-style '(nil grave straight))
|
||||
(dolist (char-repl '((?‘ . ?\`) (?’ . ?\') (?“ . ?\") (?” . ?\")))
|
||||
(let ((char (car char-repl))
|
||||
(repl (cdr char-repl)))
|
||||
(when (or text-quoting-style (not (char-displayable-p char)))
|
||||
(when (and (eq repl ?\`) (eq text-quoting-style 'straight))
|
||||
(setq repl ?\'))
|
||||
(unless standard-display-table
|
||||
(setq standard-display-table (make-display-table)))
|
||||
(aset standard-display-table char
|
||||
(vector (make-glyph-code repl 'shadow))))))))
|
||||
(defun startup--setup-quote-display (&optional style)
|
||||
"If needed, display ASCII approximations to curved quotes.
|
||||
Do this by modifying `standard-display-table'. Optional STYLE
|
||||
specifies the desired quoting style, as in `text-quoting-style'.
|
||||
If STYLE is nil, display appropriately for the terminal."
|
||||
(let ((repls (let ((style-repls (assq style '((grave . "`'\"\"")
|
||||
(straight . "''\"\"")))))
|
||||
(if style-repls (cdr style-repls) (make-vector 4 nil))))
|
||||
glyph-count)
|
||||
;; REPLS is a sequence of the four replacements for "‘’“”", respectively.
|
||||
;; If STYLE is nil, infer REPLS from terminal characteristics.
|
||||
(unless style
|
||||
;; On a terminal that supports glyph codes,
|
||||
;; GLYPH-COUNT[i] is the number of times that glyph code I
|
||||
;; represents either an ASCII character or one of the 4
|
||||
;; quote characters. This assumes glyph codes are valid
|
||||
;; Elisp characters, which is a safe assumption in practice.
|
||||
(when (integerp (internal-char-font nil (max-char)))
|
||||
(setq glyph-count (make-char-table nil 0))
|
||||
(dotimes (i 132)
|
||||
(let ((glyph (internal-char-font
|
||||
nil (if (< i 128) i (aref "‘’“”" (- i 128))))))
|
||||
(when (<= 0 glyph)
|
||||
(aset glyph-count glyph (1+ (aref glyph-count glyph)))))))
|
||||
(dotimes (i 2)
|
||||
(let ((lq (aref "‘“" i)) (rq (aref "’”" i))
|
||||
(lr (aref "`\"" i)) (rr (aref "'\"" i))
|
||||
(i2 (* i 2)))
|
||||
(unless (if glyph-count
|
||||
;; On a terminal that supports glyph codes, use
|
||||
;; ASCII replacements unless both quotes are displayable.
|
||||
;; If not using ASCII replacements, highlight
|
||||
;; quotes unless they are both unique among the
|
||||
;; 128 + 4 characters of concern.
|
||||
(let ((lglyph (internal-char-font nil lq))
|
||||
(rglyph (internal-char-font nil rq)))
|
||||
(when (and (<= 0 lglyph) (<= 0 rglyph))
|
||||
(setq lr lq rr rq)
|
||||
(and (= 1 (aref glyph-count lglyph))
|
||||
(= 1 (aref glyph-count rglyph)))))
|
||||
;; On a terminal that does not support glyph codes, use
|
||||
;; ASCII replacements unless both quotes are displayable.
|
||||
(and (char-displayable-p lq)
|
||||
(char-displayable-p rq)))
|
||||
(aset repls i2 lr)
|
||||
(aset repls (1+ i2) rr)))))
|
||||
(dotimes (i 4)
|
||||
(let ((char (aref "‘’“”" i))
|
||||
(repl (aref repls i)))
|
||||
(if repl
|
||||
(aset (or standard-display-table
|
||||
(setq standard-display-table (make-display-table)))
|
||||
char (vector (make-glyph-code repl 'escape-glyph)))
|
||||
(when standard-display-table
|
||||
(aset standard-display-table char nil)))))))
|
||||
|
||||
(defun command-line ()
|
||||
"A subroutine of `normal-top-level'.
|
||||
|
@ -1239,11 +1281,6 @@ the `--debug-init' option to view a complete error backtrace."
|
|||
;; unibyte (display table, terminal coding system &c).
|
||||
(set-language-environment current-language-environment)))
|
||||
|
||||
;; Setup quote display again, if the init file sets
|
||||
;; text-quoting-style to a non-nil value.
|
||||
(when (and (not noninteractive) text-quoting-style)
|
||||
(startup--setup-quote-display))
|
||||
|
||||
;; Do this here in case the init file sets mail-host-address.
|
||||
(if (equal user-mail-address "")
|
||||
(setq user-mail-address (or (getenv "EMAIL")
|
||||
|
|
|
@ -1786,18 +1786,23 @@ update_auto_fontset_alist (Lisp_Object font_object, Lisp_Object fontset)
|
|||
}
|
||||
}
|
||||
|
||||
/* Return a description of the font at POSITION in the current buffer.
|
||||
If the 2nd optional arg CH is non-nil, it is a character to check
|
||||
the font instead of the character at POSITION.
|
||||
|
||||
/* Return a cons (FONT-OBJECT . GLYPH-CODE).
|
||||
For a graphical display, return a cons (FONT-OBJECT . GLYPH-CODE).
|
||||
FONT-OBJECT is the font for the character at POSITION in the current
|
||||
buffer. This is computed from all the text properties and overlays
|
||||
that apply to POSITION. POSITION may be nil, in which case,
|
||||
FONT-SPEC is the font for displaying the character CH with the
|
||||
default face.
|
||||
default face. GLYPH-CODE is the glyph code in the font to use for
|
||||
the character.
|
||||
|
||||
GLYPH-CODE is the glyph code in the font to use for the character.
|
||||
|
||||
If the 2nd optional arg CH is non-nil, it is a character to check
|
||||
the font instead of the character at POSITION.
|
||||
For a text terminal, return a nonnegative integer glyph code for
|
||||
the character, or a negative integer if the character is not
|
||||
displayable. Terminal glyph codes are system-dependent integers
|
||||
that represent displayable characters: for example, on a Linux x86
|
||||
console they represent VGA code points.
|
||||
|
||||
It returns nil in the following cases:
|
||||
|
||||
|
@ -1809,6 +1814,8 @@ update_auto_fontset_alist (Lisp_Object font_object, Lisp_Object fontset)
|
|||
(3) If POSITION is not nil, and the current buffer is not displayed
|
||||
in any window.
|
||||
|
||||
(4) For a text terminal, the terminal does not report glyph codes.
|
||||
|
||||
In addition, the returned font name may not take into account of
|
||||
such redisplay engine hooks as what used in jit-lock-mode if
|
||||
POSITION is currently not visible. */
|
||||
|
@ -1860,7 +1867,7 @@ DEFUN ("internal-char-font", Finternal_char_font, Sinternal_char_font, 1, 2, 0,
|
|||
if (! CHAR_VALID_P (c))
|
||||
return Qnil;
|
||||
if (!FRAME_WINDOW_P (f))
|
||||
return Qnil;
|
||||
return terminal_glyph_code (FRAME_TERMINAL (f), c);
|
||||
/* We need the basic faces to be valid below, so recompute them if
|
||||
some code just happened to clear the face cache. */
|
||||
if (FRAME_FACE_CACHE (f)->used == 0)
|
||||
|
|
|
@ -383,6 +383,11 @@ struct terminal
|
|||
the selection-values. */
|
||||
Lisp_Object Vselection_alist;
|
||||
|
||||
/* If a char-table, this maps characters to terminal glyph codes.
|
||||
If t, the mapping is not available. If nil, it is not known
|
||||
whether the mapping is available. */
|
||||
Lisp_Object glyph_code_table;
|
||||
|
||||
/* All fields before `next_terminal' should be Lisp_Object and are traced
|
||||
by the GC. All fields afterwards are ignored by the GC. */
|
||||
|
||||
|
@ -690,6 +695,7 @@ extern struct terminal *get_named_terminal (const char *);
|
|||
extern struct terminal *create_terminal (enum output_method,
|
||||
struct redisplay_interface *);
|
||||
extern void delete_terminal (struct terminal *);
|
||||
extern Lisp_Object terminal_glyph_code (struct terminal *, int);
|
||||
|
||||
/* The initial terminal device, created by initial_term_init. */
|
||||
extern struct terminal *initial_terminal;
|
||||
|
|
|
@ -28,6 +28,11 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
|
|||
#include "coding.h"
|
||||
#include "keyboard.h"
|
||||
|
||||
#ifdef HAVE_LINUX_KD_H
|
||||
# include <errno.h>
|
||||
# include <linux/kd.h>
|
||||
#endif
|
||||
|
||||
/* Chain of all terminals currently in use. */
|
||||
struct terminal *terminal_list;
|
||||
|
||||
|
@ -193,7 +198,7 @@ ins_del_lines (struct frame *f, int vpos, int n)
|
|||
}
|
||||
|
||||
/* Return the terminal object specified by TERMINAL. TERMINAL may
|
||||
be a terminal object, a frame, or nil for the terminal device of
|
||||
” be a terminal object, a frame, or nil for the terminal device of
|
||||
the current frame. If TERMINAL is neither from the above or the
|
||||
resulting terminal object is deleted, return NULL. */
|
||||
|
||||
|
@ -526,6 +531,65 @@ selected frame's terminal). */)
|
|||
return store_terminal_param (decode_live_terminal (terminal), parameter, value);
|
||||
}
|
||||
|
||||
#if HAVE_LINUX_KD_H
|
||||
|
||||
/* Compute the glyph code table for T. */
|
||||
|
||||
static void
|
||||
calculate_glyph_code_table (struct terminal *t)
|
||||
{
|
||||
Lisp_Object glyphtab = Qt;
|
||||
enum { initial_unipairs = 1000 };
|
||||
int entry_ct = initial_unipairs;
|
||||
struct unipair unipair_buffer[initial_unipairs];
|
||||
struct unipair *entries = unipair_buffer;
|
||||
struct unipair *alloced = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
int fd = fileno (t->display_info.tty->output);
|
||||
struct unimapdesc unimapdesc = { entry_ct, entries };
|
||||
if (ioctl (fd, GIO_UNIMAP, &unimapdesc) == 0)
|
||||
{
|
||||
glyphtab = Fmake_char_table (Qnil, make_number (-1));
|
||||
for (int i = 0; i < unimapdesc.entry_ct; i++)
|
||||
char_table_set (glyphtab, entries[i].unicode,
|
||||
make_number (entries[i].fontpos));
|
||||
break;
|
||||
}
|
||||
if (errno != ENOMEM)
|
||||
break;
|
||||
entry_ct = unimapdesc.entry_ct;
|
||||
entries = alloced = xrealloc (alloced, entry_ct * sizeof *alloced);
|
||||
}
|
||||
|
||||
xfree (alloced);
|
||||
t->glyph_code_table = glyphtab;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Return the glyph code in T of character CH, or -1 if CH does not
|
||||
have a font position in T, or nil if T does not report glyph codes. */
|
||||
|
||||
Lisp_Object
|
||||
terminal_glyph_code (struct terminal *t, int ch)
|
||||
{
|
||||
#if HAVE_LINUX_KD_H
|
||||
if (t->type == output_termcap)
|
||||
{
|
||||
/* As a hack, recompute the table when CH is the maximum
|
||||
character. */
|
||||
if (NILP (t->glyph_code_table) || ch == MAX_CHAR)
|
||||
calculate_glyph_code_table (t);
|
||||
|
||||
if (! EQ (t->glyph_code_table, Qt))
|
||||
return char_table_ref (t->glyph_code_table, ch);
|
||||
}
|
||||
#endif
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
/* Initial frame has no device-dependent output data, but has
|
||||
face cache which should be freed when the frame is deleted. */
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue