commit 30ebb54410d18a4f782fe39d21c1941f9852ec8f (HEAD, refs/remotes/origin/master) Merge: 558c4dafa3 31ef751f94 Author: Stefan Kangas Date: Tue Feb 1 06:57:16 2022 +0100 Merge from origin/emacs-28 31ef751f94 Clarify documentation of a "face's font" 29bdedf12f Bind Qdebugger to Qdebug in signal_or_quit. commit 558c4dafa309445cd8ffc568303e2189f4effc03 Author: Po Lu Date: Tue Feb 1 05:39:28 2022 +0000 Clean up Haiku display structures * src/haikufns.c (haiku_set_parent_frame): Set `parent_desc' correctly. * src/haikuterm.h (C_FRAME, C_FONT, C_TERMINAL): (struct haiku_display_info): (struct haiku_output): Get rid of C_* preprocessor defines, since these files are no longer included in any way by C++ files. diff --git a/src/haikufns.c b/src/haikufns.c index 8f5dae1a2b..eb736f1153 100644 --- a/src/haikufns.c +++ b/src/haikufns.c @@ -418,13 +418,20 @@ haiku_set_parent_frame (struct frame *f, } if (!NILP (old_value)) - EmacsWindow_unparent (FRAME_HAIKU_WINDOW (f)); + { + EmacsWindow_unparent (FRAME_HAIKU_WINDOW (f)); + FRAME_OUTPUT_DATA (f)->parent_desc = NULL; + } if (!NILP (new_value)) { EmacsWindow_parent_to (FRAME_HAIKU_WINDOW (f), FRAME_HAIKU_WINDOW (p)); BWindow_set_offset (FRAME_HAIKU_WINDOW (f), f->left_pos, f->top_pos); + + /* This isn't actually used for anything, but makes the + `parent-id' parameter correct. */ + FRAME_OUTPUT_DATA (f)->parent_desc = FRAME_HAIKU_WINDOW (p); } fset_parent_frame (f, new_value); unblock_input (); diff --git a/src/haikuterm.h b/src/haikuterm.h index de302883e4..de607e6dc5 100644 --- a/src/haikuterm.h +++ b/src/haikuterm.h @@ -32,10 +32,6 @@ along with GNU Emacs. If not, see . */ #include "font.h" #include "systime.h" -#define C_FRAME struct frame * -#define C_FONT struct font * -#define C_TERMINAL struct terminal * - #define HAVE_CHAR_CACHE_MAX 65535 extern int popup_activated_p; @@ -64,7 +60,7 @@ struct haiku_display_info { /* Chain of all haiku_display_info structures. */ struct haiku_display_info *next; - C_TERMINAL terminal; + struct terminal *terminal; Lisp_Object name_list_element; Lisp_Object color_map; @@ -86,7 +82,6 @@ struct haiku_display_info int n_planes; int color_p; - Window root_window; Lisp_Object rdb; Emacs_Cursor vertical_scroll_bar_cursor; @@ -94,9 +89,9 @@ struct haiku_display_info Mouse_HLInfo mouse_highlight; - C_FRAME highlight_frame; - C_FRAME last_mouse_frame; - C_FRAME last_mouse_motion_frame; + struct frame *highlight_frame; + struct frame *last_mouse_frame; + struct frame *last_mouse_motion_frame; int last_mouse_motion_x; int last_mouse_motion_y; @@ -110,6 +105,8 @@ struct haiku_display_info double resx, resy; Time last_mouse_movement_time; + + Window root_window; }; struct haiku_output @@ -160,7 +157,7 @@ struct haiku_output int menu_bar_open_p; - C_FONT font; + struct font *font; int hourglass_p; uint32_t cursor_fg; commit cfbb6359cebb6c0465bf132ab5a88c095373c4d0 Author: Po Lu Date: Tue Feb 1 13:24:31 2022 +0800 ; * lisp/select.el (gui--selection-value-internal): Fix comment. diff --git a/lisp/select.el b/lisp/select.el index d9f537cfce..ca9061c0b0 100644 --- a/lisp/select.el +++ b/lisp/select.el @@ -170,11 +170,12 @@ decided by `x-select-request-type'. The return value is already decoded. If `gui-get-selection' signals an error, return nil." ;; The doc string of `interprogram-paste-function' says to return ;; nil if no other program has provided text to paste. - (unless (and (memq window-system '(x haiku)) - ;; gui-backend-selection-p might be unreliable on other - ;; window systems. - (eq type 'CLIPBOARD) - (gui-backend-selection-owner-p type)) + (unless (and + ;; `gui-backend-selection-owner-p' might be unreliable on + ;; some other window systems. + (memq window-system '(x haiku)) + (eq type 'CLIPBOARD) + (gui-backend-selection-owner-p type)) (let ((request-type (if (memq window-system '(x pgtk)) (or x-select-request-type '(UTF8_STRING COMPOUND_TEXT STRING text/plain\;charset=utf-8)) commit 7b63c00af48237e837daf41ea0b41c756a2d8265 Author: Stefan Kangas Date: Tue Feb 1 06:11:36 2022 +0100 Update publicsuffix.txt from upstream * etc/publicsuffix.txt: Update from https://publicsuffix.org/list/public_suffix_list.dat dated 2022-01-27 20:16:15 UTC. diff --git a/etc/publicsuffix.txt b/etc/publicsuffix.txt index fb018d626a..c67235fae0 100644 --- a/etc/publicsuffix.txt +++ b/etc/publicsuffix.txt @@ -3765,11 +3765,10 @@ org.kw // ky : http://www.icta.ky/da_ky_reg_dom.php // Confirmed by registry 2008-06-17 ky -edu.ky -gov.ky com.ky -org.ky +edu.ky net.ky +org.ky // kz : https://en.wikipedia.org/wiki/.kz // see also: http://www.nic.kz/rules/index.jsp @@ -11106,6 +11105,10 @@ cloudns.us // Submitted by Angelo Gladding cnpy.gdn +// Codeberg e. V. : https://codeberg.org +// Submitted by Moritz Marquardt +codeberg.page + // CoDNS B.V. co.nl co.no @@ -11965,6 +11968,10 @@ futuremailing.at // Submitted by David Illsley service.gov.uk +// CDDO : https://www.gov.uk/guidance/get-an-api-domain-on-govuk +// Submitted by Jamie Tanna +api.gov.uk + // Gehirn Inc. : https://www.gehirn.co.jp/ // Submitted by Kohei YOSHIDA gehirn.ne.jp @@ -13480,6 +13487,10 @@ gdynia.pl med.pl sopot.pl +// team.blue https://team.blue +// Submitted by Cedric Dubois +site.tb-hosting.com + // Teckids e.V. : https://www.teckids.org // Submitted by Dominik George edugit.io commit 103ddfe387333891780b93eec652cbcf1519156c Author: Po Lu Date: Tue Feb 1 12:58:00 2022 +0800 Display images with a mask correctly when `alpha-background' is set * src/xterm.c (x_query_frame_background_color): Return value adjusted for background alpha. (x_draw_image_glyph_string): Respect `alpha-background' when generating background pixmap. diff --git a/src/xterm.c b/src/xterm.c index 2fc336f72a..843483b594 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -2993,12 +2993,23 @@ x_query_colors (struct frame *f, XColor *colors, int ncolors) XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), colors, ncolors); } -/* Store F's background color into *BGCOLOR. */ +/* Store F's real background color into *BGCOLOR. */ static void x_query_frame_background_color (struct frame *f, XColor *bgcolor) { - bgcolor->pixel = FRAME_BACKGROUND_PIXEL (f); + unsigned long background = FRAME_BACKGROUND_PIXEL (f); + + if (FRAME_DISPLAY_INFO (f)->alpha_bits) + { + background = (background & ~FRAME_DISPLAY_INFO (f)->alpha_mask); + background |= (((unsigned long) (f->alpha_background * 0xffff) + >> (16 - FRAME_DISPLAY_INFO (f)->alpha_bits)) + << FRAME_DISPLAY_INFO (f)->alpha_offset); + } + + bgcolor->pixel = background; + x_query_colors (f, bgcolor, 1); } @@ -4075,12 +4086,34 @@ x_draw_image_glyph_string (struct glyph_string *s) else { XGCValues xgcv; - XGetGCValues (display, s->gc, GCForeground | GCBackground, - &xgcv); - XSetForeground (display, s->gc, xgcv.background); - XFillRectangle (display, pixmap, s->gc, - 0, 0, s->background_width, s->height); - XSetForeground (display, s->gc, xgcv.foreground); +#if defined HAVE_XRENDER && (RENDER_MAJOR > 0 || (RENDER_MINOR >= 2)) + if (FRAME_DISPLAY_INFO (s->f)->alpha_bits + && FRAME_CHECK_XR_VERSION (s->f, 0, 2) + && FRAME_X_PICTURE_FORMAT (s->f)) + { + XRenderColor xc; + XRenderPictureAttributes attrs; + Picture pict; + memset (&attrs, 0, sizeof attrs); + + pict = XRenderCreatePicture (display, pixmap, + FRAME_X_PICTURE_FORMAT (s->f), + 0, &attrs); + x_xrender_color_from_gc_background (s->f, s->gc, &xc, true); + XRenderFillRectangle (FRAME_X_DISPLAY (s->f), PictOpSrc, pict, + &xc, 0, 0, s->background_width, s->height); + XRenderFreePicture (display, pict); + } + else +#endif + { + XGetGCValues (display, s->gc, GCForeground | GCBackground, + &xgcv); + XSetForeground (display, s->gc, xgcv.background); + XFillRectangle (display, pixmap, s->gc, + 0, 0, s->background_width, s->height); + XSetForeground (display, s->gc, xgcv.foreground); + } } } else commit 99c637499ec2bc0babb5d98b16f9c578952d54fd Author: Po Lu Date: Tue Feb 1 10:13:15 2022 +0800 Only apply last change to the clipboard * lisp/select.el (gui--selection-value-internal): Only return nil if we own the clipboard. diff --git a/lisp/select.el b/lisp/select.el index 420967c1b0..d9f537cfce 100644 --- a/lisp/select.el +++ b/lisp/select.el @@ -173,6 +173,7 @@ decoded. If `gui-get-selection' signals an error, return nil." (unless (and (memq window-system '(x haiku)) ;; gui-backend-selection-p might be unreliable on other ;; window systems. + (eq type 'CLIPBOARD) (gui-backend-selection-owner-p type)) (let ((request-type (if (memq window-system '(x pgtk)) (or x-select-request-type commit 16174d796f86fe31c4a20ece471bed10f23c229f Author: Po Lu Date: Tue Feb 1 02:03:05 2022 +0000 Avoid extraneous selection querying if we own the selection * lisp/select.el (gui--selection-value-internal): Return nil if `gui-backend-selection-owner-p' on window systems where it is reliable. diff --git a/lisp/select.el b/lisp/select.el index 7f29f02dab..420967c1b0 100644 --- a/lisp/select.el +++ b/lisp/select.el @@ -168,20 +168,26 @@ text/plain\\;charset=utf-8)." Call `gui-get-selection' with an appropriate DATA-TYPE argument decided by `x-select-request-type'. The return value is already decoded. If `gui-get-selection' signals an error, return nil." - (let ((request-type (if (memq window-system '(x pgtk)) - (or x-select-request-type - '(UTF8_STRING COMPOUND_TEXT STRING text/plain\;charset=utf-8)) - 'STRING)) - text) - (with-demoted-errors "gui-get-selection: %S" - (if (consp request-type) - (while (and request-type (not text)) - (setq text (gui-get-selection type (car request-type))) - (setq request-type (cdr request-type))) - (setq text (gui-get-selection type request-type)))) - (if text - (remove-text-properties 0 (length text) '(foreign-selection nil) text)) - text)) + ;; The doc string of `interprogram-paste-function' says to return + ;; nil if no other program has provided text to paste. + (unless (and (memq window-system '(x haiku)) + ;; gui-backend-selection-p might be unreliable on other + ;; window systems. + (gui-backend-selection-owner-p type)) + (let ((request-type (if (memq window-system '(x pgtk)) + (or x-select-request-type + '(UTF8_STRING COMPOUND_TEXT STRING text/plain\;charset=utf-8)) + 'STRING)) + text) + (with-demoted-errors "gui-get-selection: %S" + (if (consp request-type) + (while (and request-type (not text)) + (setq text (gui-get-selection type (car request-type))) + (setq request-type (cdr request-type))) + (setq text (gui-get-selection type request-type)))) + (if text + (remove-text-properties 0 (length text) '(foreign-selection nil) text)) + text))) (defun gui-selection-value () (let ((clip-text commit d6d73224a21506b0ba31fd03bd99c5535ce3bb9c Author: Po Lu Date: Tue Feb 1 09:38:26 2022 +0800 Make fringe bitmaps respect alpha-background * src/xterm.c (x_draw_fringe_bitmap): Respect alpha-background on non-overlay fringe bitmaps. * src/xterm.h (struct x_display_info): New field `alpha_mask'. diff --git a/src/xterm.c b/src/xterm.c index 5bcb77bbeb..2fc336f72a 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -2032,6 +2032,7 @@ x_draw_fringe_bitmap (struct window *w, struct glyph_row *row, struct draw_fring Pixmap pixmap, clipmask = None; int depth = FRAME_DISPLAY_INFO (f)->n_planes; XGCValues gcv; + unsigned long background = face->background; #ifdef HAVE_XRENDER Picture picture = None; XRenderPictureAttributes attrs; @@ -2044,6 +2045,14 @@ x_draw_fringe_bitmap (struct window *w, struct glyph_row *row, struct draw_fring else bits = (char *) p->bits + p->dh; + if (FRAME_DISPLAY_INFO (f)->alpha_bits) + { + background = (background & ~FRAME_DISPLAY_INFO (f)->alpha_mask); + background |= (((unsigned long) (f->alpha_background * 0xffff) + >> (16 - FRAME_DISPLAY_INFO (f)->alpha_bits)) + << FRAME_DISPLAY_INFO (f)->alpha_offset); + } + /* Draw the bitmap. I believe these small pixmaps can be cached by the server. */ pixmap = XCreatePixmapFromBitmapData (display, drawable, bits, p->wd, p->h, @@ -2051,7 +2060,7 @@ x_draw_fringe_bitmap (struct window *w, struct glyph_row *row, struct draw_fring ? (p->overlay_p ? face->background : f->output_data.x->cursor_pixel) : face->foreground), - face->background, depth); + background, depth); #ifdef HAVE_XRENDER if (FRAME_X_PICTURE_FORMAT (f) @@ -15574,6 +15583,7 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) if (channel_mask) get_bits_and_offset (channel_mask, &dpyinfo->alpha_bits, &dpyinfo->alpha_offset); + dpyinfo->alpha_mask = channel_mask; } else #endif @@ -15594,6 +15604,7 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) if (alpha_mask) get_bits_and_offset (alpha_mask, &dpyinfo->alpha_bits, &dpyinfo->alpha_offset); + dpyinfo->alpha_mask = alpha_mask; } } } diff --git a/src/xterm.h b/src/xterm.h index c8c491a7d3..02270d6936 100644 --- a/src/xterm.h +++ b/src/xterm.h @@ -462,6 +462,7 @@ struct x_display_info /* Bits and shifts to use to compose pixel values on TrueColor visuals. */ int red_bits, blue_bits, green_bits, alpha_bits; int red_offset, blue_offset, green_offset, alpha_offset; + unsigned long alpha_mask; /* The type of window manager we have. If we move FRAME_OUTER_WINDOW to x/y 0/0, some window managers (type A) puts the window manager commit 63edde9f0e811a629c578fd1db9a826c414a2df8 Author: Lars Ingebrigtsen Date: Mon Jan 31 22:36:25 2022 +0100 Fix nnregistry byte compilation warning * lisp/gnus/nnregistry.el (nnregistry-server-opened) (nnregistry-open-server): Fix byte compilation warning. diff --git a/lisp/gnus/nnregistry.el b/lisp/gnus/nnregistry.el index d042981ca9..4a799acad9 100644 --- a/lisp/gnus/nnregistry.el +++ b/lisp/gnus/nnregistry.el @@ -36,7 +36,7 @@ (nnoo-declare nnregistry) (deffoo nnregistry-server-opened (_server) - gnus-registry-enabled) + gnus-registry-db) (deffoo nnregistry-close-server (_server &optional _defs) t) @@ -45,7 +45,7 @@ nil) (deffoo nnregistry-open-server (_server &optional _defs) - gnus-registry-enabled) + gnus-registry-db) (defvar nnregistry-within-nnregistry nil) commit cce477cad7ffffbfc1a21e9dd711b32f8e2b3ea3 Author: Stefan Monnier Date: Mon Jan 31 16:25:09 2022 -0500 (byte-compile-eval): Adjust to changes in `load-history` The `function-history` patch introduced a regression which caused spurious compiler warnings. Fix it. The new code also fixes a bug in the old code, thus causing some new non-spurious warnings. Fix them as well. * lisp/emacs-lisp/bytecomp.el (byte-compile-eval): Adjust to changes in `load-history`. * lisp/gnus/gnus-group.el (nnrss-discover-feed) (nnrss-save-server-data): Use `declare-function`. * lisp/cedet/semantic/wisent/comp.el (wisent-defcontext) (wisent-with-context): * lisp/emacs-lisp/comp.el (comp-op-case): Silence compiler warning. diff --git a/lisp/cedet/semantic/wisent/comp.el b/lisp/cedet/semantic/wisent/comp.el index f842b3c364..ba67d25060 100644 --- a/lisp/cedet/semantic/wisent/comp.el +++ b/lisp/cedet/semantic/wisent/comp.el @@ -65,6 +65,7 @@ (defmacro wisent-defcontext (name &rest vars) "Define a context NAME that will bind variables VARS." (declare (indent 1)) + (declare-function wisent-context-name nil (name)) (let* ((context (wisent-context-name name)) (declarations (mapcar (lambda (v) (list 'defvar v)) vars))) `(progn @@ -75,6 +76,7 @@ (defmacro wisent-with-context (name &rest body) "Bind variables in context NAME then eval BODY." (declare (indent 1)) + (declare-function wisent-context-bindings nil (name)) `(dlet ,(wisent-context-bindings name) ,@body)) diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el index 2f4bf66343..9c664ff8fe 100644 --- a/lisp/emacs-lisp/bytecomp.el +++ b/lisp/emacs-lisp/bytecomp.el @@ -1031,30 +1031,23 @@ Each function's symbol gets added to `byte-compile-noruntime-functions'." (hist-nil-orig current-load-list)) (prog1 (eval form lexical-binding) (when (byte-compile-warning-enabled-p 'noruntime) - (let ((hist-new load-history) - (hist-nil-new current-load-list)) + (let* ((hist-new + ;; Get new `current-load-list' for the locally defined funs. + (cons (butlast current-load-list + (length hist-nil-orig)) + load-history))) ;; Go through load-history, look for newly loaded files ;; and mark all the functions defined therein. (while (and hist-new (not (eq hist-new hist-orig))) - (let ((xs (pop hist-new)) - old-autoloads) + (let ((xs (pop hist-new))) ;; Make sure the file was not already loaded before. (unless (assoc (car xs) hist-orig) (dolist (s xs) - (cond - ((and (consp s) (eq t (car s))) - (push (cdr s) old-autoloads)) - ((and (consp s) (memq (car s) '(autoload defun))) - (unless (memq (cdr s) old-autoloads) - (push (cdr s) byte-compile-noruntime-functions)))))))) - ;; Go through current-load-list for the locally defined funs. - (let (old-autoloads) - (while (and hist-nil-new (not (eq hist-nil-new hist-nil-orig))) - (let ((s (pop hist-nil-new))) - (when (and (symbolp s) (not (memq s old-autoloads))) - (push s byte-compile-noruntime-functions)) - (when (and (consp s) (eq t (car s))) - (push (cdr s) old-autoloads)))))))))) + (pcase s + (`(defun . ,f) + (unless (seq-some #'autoloadp + (get (cdr s) 'function-history)) + (push f byte-compile-noruntime-functions))))))))))))) (defun byte-compile-eval-before-compile (form) "Evaluate FORM for `eval-and-compile'." diff --git a/lisp/emacs-lisp/comp.el b/lisp/emacs-lisp/comp.el index a23169aa0f..9c2fc93821 100644 --- a/lisp/emacs-lisp/comp.el +++ b/lisp/emacs-lisp/comp.el @@ -1767,6 +1767,7 @@ This is responsible for generating the proper stack adjustment, when known, and the annotation emission." (declare (debug (body)) (indent defun)) + (declare-function comp-body-eff nil (body op-name sp-delta)) `(pcase op ,@(cl-loop for (op . body) in cases for sp-delta = (gethash op comp-op-stack-info) diff --git a/lisp/gnus/gnus-group.el b/lisp/gnus/gnus-group.el index d3a94e9f4e..8937df2601 100644 --- a/lisp/gnus/gnus-group.el +++ b/lisp/gnus/gnus-group.el @@ -3135,9 +3135,9 @@ If SOLID (the prefix), create a solid group." (if (derived-mode-p 'gnus-summary-mode) 'summary 'group)))))) (defvar nnrss-group-alist) -(eval-when-compile - (defun nnrss-discover-feed (_arg)) - (defun nnrss-save-server-data (_arg))) +(declare-function nnrss-discover-feed "nnrss" (url)) +(declare-function nnrss-save-server-data "nnrss" (server)) + (defun gnus-group-make-rss-group (&optional url) "Given a URL, discover if there is an RSS feed. If there is, use Gnus to create an nnrss group" commit be2566eeab627dd8c38cfb3adb678a925af300bc Author: Alan Mackenzie Date: Mon Jan 31 19:46:27 2022 +0000 Enlarge max-specpdl-size for generation of files in .../admin/grammars * admin/grammars/Makefile.in: Add a --eval clause to set max-specpdl-size to 5000 (previously 2500) for these targets. diff --git a/admin/grammars/Makefile.in b/admin/grammars/Makefile.in index 6f69943089..4ca88982cd 100644 --- a/admin/grammars/Makefile.in +++ b/admin/grammars/Makefile.in @@ -34,7 +34,8 @@ top_builddir = @top_builddir@ unexport EMACSDATA EMACSDOC EMACSLOADPATH EMACSPATH EMACS = ${top_builddir}/src/emacs -emacs = "${EMACS}" -batch --no-site-file --no-site-lisp --eval '(setq load-prefer-newer t)' +emacs = "${EMACS}" -batch --no-site-file --no-site-lisp \ + --eval '(setq max-specpdl-size 5000)' --eval '(setq load-prefer-newer t)' make_bovine = ${emacs} -l semantic/bovine/grammar -f bovine-batch-make-parser make_wisent = ${emacs} -l semantic/wisent/grammar -f wisent-batch-make-parser commit 5819fcb63b42a302a3b3588646cf3e043dc07a39 Author: Eric Abrahamsen Date: Mon Jan 24 16:24:10 2022 -0800 Don't remove dummy.group from gnus-newsrc-alist on Gnus save bug#53352 * lisp/gnus/gnus-start.el (gnus-gnus-to-quick-newsrc-format): This function was removing dummy.group from the global value of `gnus-newsrc-alist' on save; we only wanted to remove it temporarily. diff --git a/lisp/gnus/gnus-start.el b/lisp/gnus/gnus-start.el index 2cf11fb12f..dd9c277805 100644 --- a/lisp/gnus/gnus-start.el +++ b/lisp/gnus/gnus-start.el @@ -2867,12 +2867,6 @@ SPECIFIC-VARIABLES, or those in `gnus-variable-list'." (princ "(setq gnus-newsrc-file-version ") (princ (gnus-prin1-to-string gnus-version)) (princ ")\n")) - ;; Sort `gnus-newsrc-alist' according to order in - ;; `gnus-group-list'. - (setq gnus-newsrc-alist - (mapcar (lambda (g) - (nth 1 (gethash g gnus-newsrc-hashtb))) - (delete "dummy.group" gnus-group-list))) (let* ((print-quoted t) (print-escape-multibyte nil) (print-escape-nonascii t) @@ -2891,17 +2885,20 @@ SPECIFIC-VARIABLES, or those in `gnus-variable-list'." ;; Remove the `gnus-killed-list' from the list of variables ;; to be saved, if required. (delq 'gnus-killed-list (copy-sequence gnus-variable-list))))) - ;; Encode group names in `gnus-newsrc-alist' and - ;; `gnus-topic-alist' in order to keep newsrc.eld files - ;; compatible with older versions of Gnus. At some point, - ;; if/when a new version of Gnus is released, stop doing - ;; this and move the corresponding decode in - ;; `gnus-read-newsrc-el-file' into a conversion routine. + ;; Sort `gnus-newsrc-alist' according to order in + ;; `gnus-group-list'. Encode group names in + ;; `gnus-newsrc-alist' and `gnus-topic-alist' in order to + ;; keep newsrc.eld files compatible with older versions of + ;; Gnus. At some point, if/when a new version of Gnus is + ;; released, stop doing this and move the corresponding + ;; decode in `gnus-read-newsrc-el-file' into a conversion + ;; routine. (gnus-newsrc-alist - (mapcar (lambda (info) - (cons (encode-coding-string (car info) 'utf-8-emacs) - (cdr info))) - gnus-newsrc-alist)) + (mapcar (lambda (group) + (cons (encode-coding-string group 'utf-8-emacs) + (cdadr (gethash group + gnus-newsrc-hashtb)))) + (remove "dummy.group" gnus-group-list))) (gnus-topic-alist (when (memq 'gnus-topic-alist variables) (mapcar (lambda (elt) commit 161382f76d9afd8a4e8f4499d3479bd38a74bada Author: Eric Abrahamsen Date: Mon Jan 24 16:20:44 2022 -0800 Obsolete gnus-registry-enabled in favor of checking gnus-registry-db * lisp/gnus/gnus-registry.el (gnus-registry-enabled): Obsolete this variable; recommend using `gnus-registry-db' as a boolean instead. (gnus-registry-load, gnus-registry-register-message-ids, gnus-registry-article-marks-to-chars, gnus-registry-article-marks-to-names, gnus-registry-clear, gnus-registry-install-p): In all these functions, test `gnus-registry-db' instead of `gnus-registry-enabled'. We no longer set or clear that variable. diff --git a/lisp/gnus/gnus-registry.el b/lisp/gnus/gnus-registry.el index ccdaabe3c6..8cefb09b66 100644 --- a/lisp/gnus/gnus-registry.el +++ b/lisp/gnus/gnus-registry.el @@ -163,7 +163,9 @@ nnmairix groups are specifically excluded because they are ephemeral." :type 'boolean :version "28.1") -(defvar gnus-registry-enabled nil) +(make-obsolete-variable + 'gnus-registry-enabled + "Check for non-nil value of `gnus-registry-db'" "29.1") (defvar gnus-summary-misc-menu) ;; Avoid byte compiler warning. @@ -360,8 +362,7 @@ This is not required after changing `gnus-registry-cache-file'." (progn (gnus-registry-read file) (gnus-registry-install-hooks) - (gnus-registry-install-shortcuts) - (setq gnus-registry-enabled t)) + (gnus-registry-install-shortcuts)) (file-error ;; Fix previous mis-naming of the registry file. (let ((old-file-name @@ -851,7 +852,7 @@ Overrides existing keywords with FORCE set non-nil." (defun gnus-registry-register-message-ids () "Register the Message-ID of every article in the group." - (unless (or (null gnus-registry-enabled) + (unless (or (null gnus-registry-db) (null gnus-registry-register-all) (gnus-parameter-registry-ignore gnus-newsgroup-name)) (dolist (article gnus-newsgroup-articles) @@ -1010,7 +1011,7 @@ Uses `gnus-registry-marks' to find what shortcuts to install." ;; (defalias 'gnus-user-format-function-M #'gnus-registry-article-marks-to-chars) (defun gnus-registry-article-marks-to-chars (headers) "Show the marks for an article by the :char property." - (if gnus-registry-enabled + (if gnus-registry-db (let* ((id (mail-header-message-id headers)) (marks (when id (gnus-registry-get-id-key id 'mark)))) (concat (delq nil @@ -1026,7 +1027,7 @@ Uses `gnus-registry-marks' to find what shortcuts to install." ;; (defalias 'gnus-user-format-function-M #'gnus-registry-article-marks-to-names) (defun gnus-registry-article-marks-to-names (headers) "Show the marks for an article by name." - (if gnus-registry-enabled + (if gnus-registry-db (let* ((id (mail-header-message-id headers)) (marks (when id (gnus-registry-get-id-key id 'mark)))) (mapconcat #'symbol-name marks ",")) @@ -1177,8 +1178,7 @@ non-nil." (defun gnus-registry-clear () "Clear the registry." (gnus-registry-unload-hook) - (setq gnus-registry-db nil - gnus-registry-enabled nil)) + (setq gnus-registry-db nil)) (gnus-add-shutdown 'gnus-registry-clear 'gnus) @@ -1220,7 +1220,7 @@ non-nil." If the registry is not already enabled, then if `gnus-registry-install' is `ask', ask the user; or if `gnus-registry-install' is non-nil, enable it." (interactive) - (unless gnus-registry-enabled + (unless gnus-registry-db (when (if (eq gnus-registry-install 'ask) (gnus-y-or-n-p (concat "Enable the Gnus registry? " @@ -1228,7 +1228,7 @@ is `ask', ask the user; or if `gnus-registry-install' is non-nil, enable it." "to get rid of this query permanently. ")) gnus-registry-install) (gnus-registry-initialize))) - gnus-registry-enabled) + (null (null gnus-registry-db))) ;; largely based on nnselect-warp-to-article (defun gnus-try-warping-via-registry () commit 70f994f6d098c6830cab1fb396d46c42782e7527 Author: Juri Linkov Date: Mon Jan 31 20:46:06 2022 +0200 * lisp/vc/vc.el (vc-diff-internal): Assume revert-buffer is in current buffer. Support the case when reverting is in the buffer with a name other than the default name "*vc-diff*". Then don't try to switch to the buffer "*vc-diff*" with an assumption that revert-buffer is always performed in the current buffer (bug#28852). diff --git a/lisp/vc/vc.el b/lisp/vc/vc.el index 0096a5fcb3..a6124acadd 100644 --- a/lisp/vc/vc.el +++ b/lisp/vc/vc.el @@ -1798,10 +1798,9 @@ Return t if the buffer had changes, nil otherwise." (coding-system-for-read (if files (vc-coding-system-for-diff (car files)) 'undecided)) (orig-diff-buffer-clone - (if (and (get-buffer buffer) revert-buffer-in-progress-p) - (with-current-buffer buffer - (clone-buffer - (generate-new-buffer-name " *vc-diff-clone*") nil))))) + (if revert-buffer-in-progress-p + (clone-buffer + (generate-new-buffer-name " *vc-diff-clone*") nil)))) ;; On MS-Windows and MS-DOS, Diff is likely to produce DOS-style ;; EOLs, which will look ugly if (car files) happens to have Unix ;; EOLs. commit cf9c40159a6bef5a23f7b23a45c03f0c6be57574 Author: Alan Mackenzie Date: Mon Jan 31 17:44:59 2022 +0000 * lisp/progmodes/cc-mode.el (c-common-init): Bind case-fold-search to nil This fixes bug #53605. diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el index 3a3413dc36..957a0b8a7c 100644 --- a/lisp/progmodes/cc-mode.el +++ b/lisp/progmodes/cc-mode.el @@ -798,43 +798,44 @@ MODE is the symbol for the mode to initialize, like `c-mode'. See `c-basic-common-init' for details. It's only optional to be compatible with old code; callers should always specify it." - (unless mode - ;; Called from an old third party package. The fallback is to - ;; initialize for C. - (c-init-language-vars-for 'c-mode)) - - (c-basic-common-init mode c-default-style) - (when mode - ;; Only initialize font locking if we aren't called from an old package. - (c-font-lock-init)) - - ;; Starting a mode is a sort of "change". So call the change functions... - (save-restriction - (widen) - (setq c-new-BEG (point-min)) - (setq c-new-END (point-max)) - (save-excursion - (let (before-change-functions after-change-functions) - (mapc (lambda (fn) - (funcall fn (point-min) (point-max))) - c-get-state-before-change-functions) - (mapc (lambda (fn) - (funcall fn (point-min) (point-max) - (- (point-max) (point-min)))) - c-before-font-lock-functions)))) - - (set (make-local-variable 'outline-regexp) "[^#\n\^M]") - (set (make-local-variable 'outline-level) 'c-outline-level) - (set (make-local-variable 'add-log-current-defun-function) - (lambda () - (or (c-cpp-define-name) (car (c-defun-name-and-limits nil))))) - (let ((rfn (assq mode c-require-final-newline))) - (when rfn - (if (boundp 'mode-require-final-newline) - (and (cdr rfn) - (set (make-local-variable 'require-final-newline) - mode-require-final-newline)) - (set (make-local-variable 'require-final-newline) (cdr rfn)))))) + (let (case-fold-search) + (unless mode + ;; Called from an old third party package. The fallback is to + ;; initialize for C. + (c-init-language-vars-for 'c-mode)) + + (c-basic-common-init mode c-default-style) + (when mode + ;; Only initialize font locking if we aren't called from an old package. + (c-font-lock-init)) + + ;; Starting a mode is a sort of "change". So call the change functions... + (save-restriction + (widen) + (setq c-new-BEG (point-min)) + (setq c-new-END (point-max)) + (save-excursion + (let (before-change-functions after-change-functions) + (mapc (lambda (fn) + (funcall fn (point-min) (point-max))) + c-get-state-before-change-functions) + (mapc (lambda (fn) + (funcall fn (point-min) (point-max) + (- (point-max) (point-min)))) + c-before-font-lock-functions)))) + + (set (make-local-variable 'outline-regexp) "[^#\n\^M]") + (set (make-local-variable 'outline-level) 'c-outline-level) + (set (make-local-variable 'add-log-current-defun-function) + (lambda () + (or (c-cpp-define-name) (car (c-defun-name-and-limits nil))))) + (let ((rfn (assq mode c-require-final-newline))) + (when rfn + (if (boundp 'mode-require-final-newline) + (and (cdr rfn) + (set (make-local-variable 'require-final-newline) + mode-require-final-newline)) + (set (make-local-variable 'require-final-newline) (cdr rfn))))))) (defun c-count-cfss (lv-alist) ;; LV-ALIST is an alist like `file-local-variables-alist'. Count how many commit 6766e30e1b0cfcf5ddd222b3d3be2ffae9164f3f Author: Lars Ingebrigtsen Date: Mon Jan 31 18:28:41 2022 +0100 Adjust toggle-menu-bar-mode-from-frame doc string * lisp/menu-bar.el (toggle-menu-bar-mode-from-frame): Adjust the doc string to reflect what it does (bug#43383). diff --git a/lisp/menu-bar.el b/lisp/menu-bar.el index b6dbf209ec..bde34ac910 100644 --- a/lisp/menu-bar.el +++ b/lisp/menu-bar.el @@ -2537,7 +2537,7 @@ Use \\[menu-bar-mode] to make the menu bar appear.")))) (put 'menu-bar-mode 'standard-value '(t)) (defun toggle-menu-bar-mode-from-frame (&optional arg) - "Toggle display of the menu bar of the current frame. + "Toggle display of the menu bar. See `menu-bar-mode' for more information." (interactive (list (or current-prefix-arg 'toggle))) (if (eq arg 'toggle) commit 31ef751f94fd028d6f1c6bcdf379a8b99769a894 (refs/remotes/origin/emacs-28) Author: Eli Zaretskii Date: Mon Jan 31 19:29:54 2022 +0200 Clarify documentation of a "face's font" * doc/lispref/display.texi (Attribute Functions) (Face Attributes): Clarify that the :font attribute of a face and the font returned by 'face-font' are by default for ASCII characters. (Bug#53664) diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi index 66823c6556..854aa06dbb 100644 --- a/doc/lispref/display.texi +++ b/doc/lispref/display.texi @@ -2549,9 +2549,10 @@ used automatically to handle certain shades of gray. @item :font The font used to display the face. Its value should be a font object -or a fontset. @xref{Low-Level Font}, for information about font -objects, font specs, and font entities. @xref{Fontsets}, for -information about fontsets. +or a fontset. If it is a font object, it specifies the font to be +used by the face for displaying ASCII characters. @xref{Low-Level +Font}, for information about font objects, font specs, and font +entities. @xref{Fontsets}, for information about fontsets. @anchor{face-font-attribute} When specifying this attribute using @code{set-face-attribute} or @@ -2994,13 +2995,19 @@ return value is always specified, use a value of @code{default} for @var{inherit}. @defun face-font face &optional frame character -This function returns the name of the font of face @var{face}. +This function returns the name of the font used by the specified +@var{face}. If the optional argument @var{frame} is specified, it returns the name -of the font of @var{face} for that frame. If @var{frame} is omitted or -@code{nil}, the selected frame is used. In the latter case, if the -optional third argument @var{character} is supplied, it returns the font -name used for @var{character}. +of the font of @var{face} for that frame; @var{frame} defaults to the +selected frame if it is @code{nil} or omitted. If @var{frame} is +@code{t}, the function reports on the font defaults for @var{face} to +be used for new frames. + +By default, the returned font is for displaying ASCII characters, but +if @var{frame} is anything but @code{t}, and the optional third +argument @var{character} is supplied, the function returns the font +name used by @var{face} for that character. @end defun @defun face-foreground face &optional frame inherit diff --git a/src/xfaces.c b/src/xfaces.c index dff5ae346d..f7ee19195f 100644 --- a/src/xfaces.c +++ b/src/xfaces.c @@ -4168,9 +4168,9 @@ If the optional argument FRAME is given, report on face FACE in that frame. If FRAME is t, report on the defaults for face FACE (for new frames). The font default for a face is either nil, or a list of the form (bold), (italic) or (bold italic). -If FRAME is omitted or nil, use the selected frame. And, in this case, -if the optional third argument CHARACTER is given, -return the font name used for CHARACTER. */) +If FRAME is omitted or nil, use the selected frame. +If FRAME is anything but t, and the optional third argument CHARACTER +is given, return the font name used by FACE for CHARACTER on FRAME. */) (Lisp_Object face, Lisp_Object frame, Lisp_Object character) { if (EQ (frame, Qt)) commit 29bdedf12ffb52d5d1458730c3d3532562336f8d Author: Alan Mackenzie Date: Mon Jan 31 17:20:45 2022 +0000 Bind Qdebugger to Qdebug in signal_or_quit. * src/eval.c (signal_or_quit): Bind the correct variable, Qdebugger (not Vdebugger) to Qdebug in the section for errors in batch jobs. (syms_of_eval): New DEFSYM for Qdebugger. diff --git a/src/eval.c b/src/eval.c index 2937e27f23..d002e81da1 100644 --- a/src/eval.c +++ b/src/eval.c @@ -1862,7 +1862,7 @@ signal_or_quit (Lisp_Object error_symbol, Lisp_Object data, bool keyboard_quit) && NILP (Vinhibit_debugger)) { ptrdiff_t count = SPECPDL_INDEX (); - specbind (Vdebugger, Qdebug); + specbind (Qdebugger, Qdebug); call_debugger (list2 (Qerror, Fcons (error_symbol, data))); unbind_to (count, Qnil); } @@ -4413,6 +4413,7 @@ might not be safe to continue. */); doc: /* Non-nil means display call stack frames as lists. */); debugger_stack_frame_as_list = 0; + DEFSYM (Qdebugger, "debugger"); DEFVAR_LISP ("debugger", Vdebugger, doc: /* Function to call to invoke debugger. If due to frame exit, args are `exit' and the value being returned; commit 402988ec333f5a8a9145b94953bbe6827b3c3b75 Author: Eli Zaretskii Date: Mon Jan 31 18:59:43 2022 +0200 Minor copyedits of 'function-history' documentation * doc/lispref/loading.texi (Where Defined): Fix indexing and punctuation. diff --git a/doc/lispref/loading.texi b/doc/lispref/loading.texi index f17514655d..68cd74c7d1 100644 --- a/doc/lispref/loading.texi +++ b/doc/lispref/loading.texi @@ -1091,6 +1091,7 @@ The value of @code{load-history} may have one element whose @sc{car} is by adding the symbols defined to the element for the file being visited, rather than replacing that element. @xref{Eval}. +@kindex function-history @r{(function symbol property)} In addition to @code{load-history}, every function keeps track of its own history in the symbol property @code{function-history}. The reason why functions are treated specially in this respect is that @@ -1099,12 +1100,11 @@ files (typically, one of them is an autoload), so in order to be able to properly @emph{unload} a file, we need to know more precisely what that file did to the function definition. -@kindex function-history The symbol property @code{function-history} holds a list of the form -@code{(@var{file1} @var{def2} @var{file2} @var{def3} ...)} where +@w{@code{(@var{file1} @var{def2} @var{file2} @var{def3} ...)}}, where @var{file1} is the last file that changed the definition and @var{def2} was the definition before @var{file1}, set by @var{file2}, -etc... Logically this list should end with the name of the first file +etc. Logically this list should end with the name of the first file that defined this function, but to save space this last element is usually omitted. commit 530cb3a3f80ec7b2f295c27b8d6c5c64eb8c02f6 Author: Lars Ingebrigtsen Date: Mon Jan 31 17:34:03 2022 +0100 Fix misplaced braces in loading.texi * doc/lispref/loading.texi (Where Defined): Fix misplaced braces. diff --git a/doc/lispref/loading.texi b/doc/lispref/loading.texi index 6179270dd3..f17514655d 100644 --- a/doc/lispref/loading.texi +++ b/doc/lispref/loading.texi @@ -1099,7 +1099,7 @@ files (typically, one of them is an autoload), so in order to be able to properly @emph{unload} a file, we need to know more precisely what that file did to the function definition. -@kindex{function-history} +@kindex function-history The symbol property @code{function-history} holds a list of the form @code{(@var{file1} @var{def2} @var{file2} @var{def3} ...)} where @var{file1} is the last file that changed the definition and commit dbf08491a5a45d88048082ba6ece1b61bdbc622b Author: Lars Ingebrigtsen Date: Mon Jan 31 17:31:09 2022 +0100 Make more ranges sort properly in describe-keymap * lisp/subr.el (keymap-canonicalize): Don't consider two-character ranges as a range (bug#11325). diff --git a/lisp/subr.el b/lisp/subr.el index fccd75361b..a1eb6fe3af 100644 --- a/lisp/subr.el +++ b/lisp/subr.el @@ -1149,8 +1149,17 @@ Subkeymaps may be modified but are not canonicalized." (setq map (map-keymap ;; -internal (lambda (key item) (if (consp key) - ;; Treat char-ranges specially. - (push (cons key item) ranges) + (if (= (car key) (1- (cdr key))) + ;; If we have a two-character range, then + ;; treat it as two separate characters + ;; (because this makes `describe-bindings' + ;; look better and shouldn't affect + ;; anything else). + (progn + (push (cons (car key) item) bindings) + (push (cons (cdr key) item) bindings)) + ;; Treat char-ranges specially. + (push (cons key item) ranges)) (push (cons key item) bindings))) map))) ;; Create the new map. diff --git a/test/lisp/help-tests.el b/test/lisp/help-tests.el index d27e3d7cd4..9c9dddcd19 100644 --- a/test/lisp/help-tests.el +++ b/test/lisp/help-tests.el @@ -286,11 +286,11 @@ M-g M-c switch-to-completions " Key Binding -+ -( .. ) short-range 1 .. 4 foo-range a .. c foo-other-range C-e foo-something +( .. ) short-range x foo-original foo-function-key1 ")))) @@ -304,12 +304,12 @@ x foo-original " Key Binding -+ -( .. ) short-range 1 .. 4 foo-range a .. c foo-other-range C-e foo-something (this binding is currently shadowed) +( .. ) short-range x foo-original (this binding is currently shadowed) foo-function-key1 commit 1d1b664fbb9232aa40d8daa54a689cfd63d38aa9 Author: Stefan Monnier Date: Mon Jan 31 11:07:06 2022 -0500 (function-history): New symbol property (bug#53632) Rework the code we have in Fdefalias that tries to keep track of definitions so as to be able to undo them later. We used to store in `load-history` when an autoload is redefined as a non-autoload and in the `autoload` symbol property we used to store the autoload data that used to be used before it got overriden. Instead, store the history of the function definition of a symbol in its `function-history` symbol property. To make this list cheap in the default case, the latest value is not stored in the list (since it's in the `symbol-function`) and neither is the first file. So if there's only been a single definition (the most common case), the list is empty and the property is just not present at all. The patch also gets rid of the `autoload` vs `defun` distinction in `load-history` which seems unnecessary (a significant part of the motivation for this patch was to get rid of the special handling of autoloads in this part of the code). * src/data.c (add_to_function_history): New function. (defalias): Use it. Don't add the `t` entries for autoloads and always use `defun` regardless of the kind of definition. Change `Vautoload_queue` to only hold the function symbols since the rest is now available from `function-history`. * src/eval.c (un_autoload): Adjust accordingly. * src/lread.c (load-history): Udate docstring. * lisp/loadhist.el (loadhist-unload-filename): New var. (unload-feature): Bind it. (loadhist-unload-element): Document its availability. (loadhist--restore-autoload): Delete var. (loadhist--unload-function): Delete function. (loadhist-unload-element): Delete the `t` and `autoload` methods. Rewrite the `defun` method using `function-history`. * lisp/help-fns.el: Require `seq`. (help-fns--autoloaded-p): Rewrite. (help-fns-function-description-header): Adjust call accordingly. * doc/lispref/loading.texi (Where Defined): Remove `autoload` and `t` entries from `load-history` since we don't generate them any more. Document the `function-history` which replaces the `autoload` property. (Unloading): Adjust symbol property name accordingly. * test/lisp/loadhist-resources/loadhist--bar.el: * test/lisp/loadhist-resources/loadhist--foo.el: New files. * test/lisp/loadhist-tests.el (loadhist-tests-unload-feature-nested) (loadhist-tests-unload-feature-notnested): New tests. diff --git a/doc/lispref/loading.texi b/doc/lispref/loading.texi index 5957b8ac38..6179270dd3 100644 --- a/doc/lispref/loading.texi +++ b/doc/lispref/loading.texi @@ -1067,13 +1067,8 @@ list elements have these forms: The symbol @var{var} was defined as a variable. @item (defun . @var{fun}) The function @var{fun} was defined. -@item (t . @var{fun}) -The function @var{fun} was previously an autoload before this library -redefined it as a function. The following element is always @code{(defun . @var{fun})}, which represents defining @var{fun} as a function. -@item (autoload . @var{fun}) -The function @var{fun} was defined as an autoload. @item (defface . @var{face}) The face @var{face} was defined. @item (require . @var{feature}) @@ -1096,6 +1091,23 @@ The value of @code{load-history} may have one element whose @sc{car} is by adding the symbols defined to the element for the file being visited, rather than replacing that element. @xref{Eval}. +In addition to @code{load-history}, every function keeps track of its +own history in the symbol property @code{function-history}. +The reason why functions are treated specially in this respect is that +it is common for functions to be defined in two steps in two different +files (typically, one of them is an autoload), so in order to be +able to properly @emph{unload} a file, we need to know more precisely +what that file did to the function definition. + +@kindex{function-history} +The symbol property @code{function-history} holds a list of the form +@code{(@var{file1} @var{def2} @var{file2} @var{def3} ...)} where +@var{file1} is the last file that changed the definition and +@var{def2} was the definition before @var{file1}, set by @var{file2}, +etc... Logically this list should end with the name of the first file +that defined this function, but to save space this last element +is usually omitted. + @node Unloading @section Unloading @cindex unloading packages @@ -1110,7 +1122,7 @@ It undefines all functions, macros, and variables defined in that library with @code{defun}, @code{defalias}, @code{defsubst}, @code{defmacro}, @code{defconst}, @code{defvar}, and @code{defcustom}. It then restores any autoloads formerly associated with those symbols. -(Loading saves these in the @code{autoload} property of the symbol.) +(Loading saves these in the @code{function-history} property of the symbol.) Before restoring the previous definitions, @code{unload-feature} runs @code{remove-hook} to remove functions defined by the library from certain diff --git a/etc/NEWS b/etc/NEWS index 4583cfb095..5d4a59975c 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -129,6 +129,9 @@ example, if point is before an Emoji sequence, pressing will delete the entire sequence, not just a single character at its beginning. +** 'load-history' does not treat autoloads specially any more. +An autoload definition appears just as a (defun . NAME) and the +(t . NAME) entries are not generated any more. * Changes in Emacs 29.1 @@ -1471,6 +1474,9 @@ The property ':position' now specifies the position of the underline when used as part of a property list specification for the ':underline' attribute. +** 'defalias' records a more precise history of definitions. +This is recorded in the `function-history` symbol property. + * Changes in Emacs 29.1 on Non-Free Operating Systems diff --git a/lisp/help-fns.el b/lisp/help-fns.el index 98a1b11e08..36c7966919 100644 --- a/lisp/help-fns.el +++ b/lisp/help-fns.el @@ -33,6 +33,7 @@ ;;; Code: (require 'cl-lib) +(require 'seq) (require 'help-mode) (require 'radix-tree) (eval-when-compile (require 'subr-x)) ;For when-let. @@ -678,19 +679,9 @@ suitable file is found, return nil." (terpri))) ;; We could use `symbol-file' but this is a wee bit more efficient. -(defun help-fns--autoloaded-p (function file) - "Return non-nil if FUNCTION has previously been autoloaded. -FILE is the file where FUNCTION was probably defined." - (let* ((file (file-name-sans-extension (file-truename file))) - (load-hist load-history) - (target (cons t function)) - found) - (while (and load-hist (not found)) - (and (stringp (caar load-hist)) - (equal (file-name-sans-extension (caar load-hist)) file) - (setq found (member target (cdar load-hist)))) - (setq load-hist (cdr load-hist))) - found)) +(defun help-fns--autoloaded-p (function) + "Return non-nil if FUNCTION has previously been autoloaded." + (seq-some #'autoloadp (get function 'function-history))) (defun help-fns--interactive-only (function) "Insert some help blurb if FUNCTION should only be used interactively." @@ -873,13 +864,13 @@ Returns a list of the form (REAL-FUNCTION DEF ALIASED REAL-DEF)." "Print a line describing FUNCTION to `standard-output'." (pcase-let* ((`(,_real-function ,def ,aliased ,real-def) (help-fns--analyze-function function)) - (file-name (find-lisp-object-file-name function (if aliased 'defun - def))) + (file-name (find-lisp-object-file-name + function (if aliased 'defun def))) (beg (if (and (or (byte-code-function-p def) (keymapp def) (memq (car-safe def) '(macro lambda closure))) (stringp file-name) - (help-fns--autoloaded-p function file-name)) + (help-fns--autoloaded-p function)) (concat "an autoloaded " (if (commandp def) "interactive ")) diff --git a/lisp/loadhist.el b/lisp/loadhist.el index 48058f4053..39481ab068 100644 --- a/lisp/loadhist.el +++ b/lisp/loadhist.el @@ -157,38 +157,35 @@ documentation of `unload-feature' for details.") ;; mode, or proposed is not nil and not major-mode, and so we use it. (funcall (or proposed 'fundamental-mode))))))) +(defvar loadhist-unload-filename nil) + (cl-defgeneric loadhist-unload-element (x) - "Unload an element from the `load-history'." + "Unload an element from the `load-history'. +The variable `loadhist-unload-filename' holds the name of the file we're +unloading." (message "Unexpected element %S in load-history" x)) -;; In `load-history', the definition of a previously autoloaded -;; function is represented by 2 entries: (t . SYMBOL) comes before -;; (defun . SYMBOL) and says we should restore SYMBOL's autoload when -;; we undefine it. -;; So we use this auxiliary variable to keep track of the last (t . SYMBOL) -;; that occurred. -(defvar loadhist--restore-autoload nil - "If non-nil, is a symbol for which to try to restore a previous autoload.") - -(cl-defmethod loadhist-unload-element ((x (head t))) - (setq loadhist--restore-autoload (cdr x))) - -(defun loadhist--unload-function (x) - (let ((fun (cdr x))) - (when (fboundp fun) - (when (fboundp 'ad-unadvise) - (ad-unadvise fun)) - (let ((aload (get fun 'autoload))) - (defalias fun - (if (and aload (eq fun loadhist--restore-autoload)) - (cons 'autoload aload) - nil))))) - (setq loadhist--restore-autoload nil)) - (cl-defmethod loadhist-unload-element ((x (head defun))) - (loadhist--unload-function x)) -(cl-defmethod loadhist-unload-element ((x (head autoload))) - (loadhist--unload-function x)) + (let* ((fun (cdr x)) + (hist (get fun 'function-history))) + (cond + ((null hist) + (defalias fun nil) + ;; Override the change that `defalias' just recorded. + (put fun 'function-history nil)) + ((equal (car hist) loadhist-unload-filename) + (defalias fun (cadr hist)) + ;; Set the history afterwards, to override the change that + ;; `defalias' records otherwise. + (put fun 'function-history (cddr hist))) + (t + ;; Unloading a file whose definition is "inactive" (i.e. has been + ;; overridden by another file): just remove it from the history, + ;; so future unloading of that other file has a chance to DTRT. + (let* ((tmp (plist-member hist loadhist-unload-filename)) + (pos (- (length hist) (length tmp)))) + (cl-assert (> pos 1)) + (setcdr (nthcdr (- pos 2) hist) (cdr tmp))))))) (cl-defmethod loadhist-unload-element ((_ (head require))) nil) (cl-defmethod loadhist-unload-element ((_ (head defface))) nil) @@ -257,6 +254,7 @@ something strange, such as redefining an Emacs function." (prin1-to-string dependents) file)))) (let* ((unload-function-defs-list (feature-symbols feature)) (file (pop unload-function-defs-list)) + (loadhist-unload-filename file) (name (symbol-name feature)) (unload-hook (intern-soft (concat name "-unload-hook"))) (unload-func (intern-soft (concat name "-unload-function")))) diff --git a/src/data.c b/src/data.c index a5a76a2755..95d29ac9e9 100644 --- a/src/data.c +++ b/src/data.c @@ -859,6 +859,43 @@ DEFUN ("fset", Ffset, Sfset, 2, 2, 0, return definition; } +static void +add_to_function_history (Lisp_Object symbol, Lisp_Object olddef) +{ + eassert (!NILP (olddef)); + + Lisp_Object past = Fget (symbol, Qfunction_history); + Lisp_Object file = Qnil; + /* FIXME: Sadly, `Vload_file_name` gives less precise information + (it's sometimes non-nil when it shoujld be nil). */ + Lisp_Object tail = Vcurrent_load_list; + FOR_EACH_TAIL_SAFE (tail) + if (NILP (XCDR (tail)) && STRINGP (XCAR (tail))) + file = XCAR (tail); + + Lisp_Object tem = Fplist_member (past, file); + if (!NILP (tem)) + { /* New def from a file used before. + Overwrite the previous record associated with this file. */ + if (EQ (tem, past)) + /* The new def is from the same file as the last change, so + there's nothing to do: unloading the file should revert to + the status before the last change rather than before this load. */ + return; + Lisp_Object pastlen = Flength (past); + Lisp_Object temlen = Flength (tem); + EMACS_INT tempos = XFIXNUM (pastlen) - XFIXNUM (temlen); + eassert (tempos > 1); + Lisp_Object prev = Fnthcdr (make_fixnum (tempos - 2), past); + /* Remove the previous info for this file. + E.g. change `hist` from (... OTHERFILE DEF3 THISFILE DEF2 ...) + to (... OTHERFILE DEF2). */ + XSETCDR (prev, XCDR (tem)); + } + /* Push new def from new file. */ + Fput (symbol, Qfunction_history, Fcons (file, Fcons (olddef, past))); +} + void defalias (Lisp_Object symbol, Lisp_Object definition) { @@ -866,19 +903,19 @@ defalias (Lisp_Object symbol, Lisp_Object definition) bool autoload = AUTOLOADP (definition); if (!will_dump_p () || !autoload) { /* Only add autoload entries after dumping, because the ones before are - not useful and else we get loads of them from the loaddefs.el. */ - Lisp_Object function = XSYMBOL (symbol)->u.s.function; - - if (AUTOLOADP (function)) - /* Remember that the function was already an autoload. */ - LOADHIST_ATTACH (Fcons (Qt, symbol)); - LOADHIST_ATTACH (Fcons (autoload ? Qautoload : Qdefun, symbol)); - - if (!NILP (Vautoload_queue) && !NILP (function)) - Vautoload_queue = Fcons (Fcons (symbol, function), Vautoload_queue); + not useful and else we get loads of them from the loaddefs.el. + That saves us about 110KB in the pdmp file (Jan 2022). */ + LOADHIST_ATTACH (Fcons (Qdefun, symbol)); + } + } - if (AUTOLOADP (function)) - Fput (symbol, Qautoload, XCDR (function)); + { + Lisp_Object olddef = XSYMBOL (symbol)->u.s.function; + if (!NILP (olddef)) + { + if (!NILP (Vautoload_queue)) + Vautoload_queue = Fcons (symbol, Vautoload_queue); + add_to_function_history (symbol, olddef); } } @@ -4171,6 +4208,7 @@ syms_of_data (void) DEFSYM (Qinteractive_form, "interactive-form"); DEFSYM (Qdefalias_fset_function, "defalias-fset-function"); + DEFSYM (Qfunction_history, "function-history"); DEFSYM (Qbyte_code_function_p, "byte-code-function-p"); diff --git a/src/eval.c b/src/eval.c index b083a00a79..1076985d09 100644 --- a/src/eval.c +++ b/src/eval.c @@ -2250,21 +2250,17 @@ this does nothing and returns nil. */) static void un_autoload (Lisp_Object oldqueue) { - Lisp_Object queue, first, second; - /* Queue to unwind is current value of Vautoload_queue. oldqueue is the shadowed value to leave in Vautoload_queue. */ - queue = Vautoload_queue; + Lisp_Object queue = Vautoload_queue; Vautoload_queue = oldqueue; while (CONSP (queue)) { - first = XCAR (queue); - second = Fcdr (first); - first = Fcar (first); - if (EQ (first, make_fixnum (0))) - Vfeatures = second; + Lisp_Object first = XCAR (queue); + if (CONSP (first) && EQ (XCAR (first), make_fixnum (0))) + Vfeatures = XCDR (first); else - Ffset (first, second); + Ffset (first, Fcar (Fcdr (Fget (first, Qfunction_history)))); queue = XCDR (queue); } } diff --git a/src/lread.c b/src/lread.c index 9910db27de..713c03243c 100644 --- a/src/lread.c +++ b/src/lread.c @@ -5240,12 +5240,9 @@ for symbols and features not associated with any file. The remaining ENTRIES in the alist element describe the functions and variables defined in that file, the features provided, and the features required. Each entry has the form `(provide . FEATURE)', -`(require . FEATURE)', `(defun . FUNCTION)', `(autoload . SYMBOL)', -`(defface . SYMBOL)', `(define-type . SYMBOL)', -`(cl-defmethod METHOD SPECIALIZERS)', or `(t . SYMBOL)'. -Entries like `(t . SYMBOL)' may precede a `(defun . FUNCTION)' entry, -and mean that SYMBOL was an autoload before this file redefined it -as a function. In addition, entries may also be single symbols, +`(require . FEATURE)', `(defun . FUNCTION)', `(defface . SYMBOL)', + `(define-type . SYMBOL)', or `(cl-defmethod METHOD SPECIALIZERS)'. +In addition, entries may also be single symbols, which means that symbol was defined by `defvar' or `defconst'. During preloading, the file name recorded is relative to the main Lisp diff --git a/test/lisp/loadhist-resources/loadhist--bar.el b/test/lisp/loadhist-resources/loadhist--bar.el new file mode 100644 index 0000000000..5c8914ed57 --- /dev/null +++ b/test/lisp/loadhist-resources/loadhist--bar.el @@ -0,0 +1,27 @@ +;;; loadhist--bar.el --- Dummy package for loadhist-tests -*- lexical-binding: t; -*- + +;; Copyright (C) 2022 Free Software Foundation, Inc. + +;; Author: Stefan Monnier + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Code: + +(autoload 'loadhist--foo-inc "loadhist--foo") + +(defun loadhist--bar-dec (x) (1- x)) + +(provide 'loadhist--bar) +;;; loadhist--bar.el ends here diff --git a/test/lisp/loadhist-resources/loadhist--foo.el b/test/lisp/loadhist-resources/loadhist--foo.el new file mode 100644 index 0000000000..3574c22013 --- /dev/null +++ b/test/lisp/loadhist-resources/loadhist--foo.el @@ -0,0 +1,29 @@ +;;; loadhist--foo.el --- Dummy package for loadhist-tests -*- lexical-binding: t; -*- + +;; Copyright (C) 2022 Free Software Foundation, Inc. + +;; Author: Stefan Monnier + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: + +;;; Code: + +(autoload 'loadhist--bar-dec "loadhist--bar") + +(defun loadhist--foo-inc (x) (1+ x)) + +(provide 'loadhist--foo) +;;; loadhist--foo.el ends here diff --git a/test/lisp/loadhist-tests.el b/test/lisp/loadhist-tests.el index a941ac0632..ef5fc164d3 100644 --- a/test/lisp/loadhist-tests.el +++ b/test/lisp/loadhist-tests.el @@ -54,4 +54,51 @@ (should-error (unload-feature 'dired)) (unload-feature 'dired-x)) +(defvar loadhist--tests-dir (file-name-directory (macroexp-file-name))) + +(ert-deftest loadhist-tests-unload-feature-nested () + (add-to-list 'load-path (expand-file-name + "loadhist-resources/" + loadhist--tests-dir)) + (declare-function loadhist--foo-inc "loadhist--foo") + (declare-function loadhist--bar-dec "loadhist--dec") + (load "loadhist--foo" nil t) + (should (and (functionp 'loadhist--bar-dec) (functionp 'loadhist--foo-inc))) + (should (autoloadp (symbol-function 'loadhist--bar-dec))) + (load "loadhist--bar" nil t) + (should (and (functionp 'loadhist--bar-dec) (functionp 'loadhist--foo-inc))) + (should (not (autoloadp (symbol-function 'loadhist--bar-dec)))) + (should (not (autoloadp (symbol-function 'loadhist--foo-inc)))) + (should (equal (list 40 42) + (list (loadhist--bar-dec 41) (loadhist--foo-inc 41)))) + (unload-feature 'loadhist--bar) + (should (and (functionp 'loadhist--bar-dec) (functionp 'loadhist--foo-inc))) + (should (autoloadp (symbol-function 'loadhist--bar-dec))) + (should (not (autoloadp (symbol-function 'loadhist--foo-inc)))) + (unload-feature 'loadhist--foo) + (should (null (symbol-function 'loadhist--bar-dec))) + (should (null (symbol-function 'loadhist--foo-inc))) + (should (null (get 'loadhist--bar-dec 'function-history))) + (should (null (get 'loadhist--foo-inc 'function-history)))) + +(ert-deftest loadhist-tests-unload-feature-notnested () + (add-to-list 'load-path (expand-file-name + "loadhist-resources/" + loadhist--tests-dir)) + (load "loadhist--foo" nil t) + (load "loadhist--bar" nil t) + (should (equal (list 40 42) + (list (loadhist--bar-dec 41) (loadhist--foo-inc 41)))) + (unload-feature 'loadhist--foo) + (should (functionp 'loadhist--bar-dec)) + (should (not (autoloadp (symbol-function 'loadhist--bar-dec)))) + (should (let ((f (symbol-function 'loadhist--foo-inc))) + ;; Both choices seem acceptable. + (or (null f) (autoloadp f)))) + (unload-feature 'loadhist--bar) + (should (null (symbol-function 'loadhist--bar-dec))) + (should (null (symbol-function 'loadhist--foo-inc))) + (should (null (get 'loadhist--bar-dec 'function-history))) + (should (null (get 'loadhist--foo-inc 'function-history)))) + ;;; loadhist-tests.el ends here commit 90bbf27f02b1e7bf9cc0f0206313795c210c565b Author: Lars Ingebrigtsen Date: Mon Jan 31 16:41:32 2022 +0100 Make Gnus address checking more resilient * lisp/gnus/gnus-art.el (article--check-suspicious-addresses): Check that we have an email address before checking the validity (bug#53651). diff --git a/lisp/gnus/gnus-art.el b/lisp/gnus/gnus-art.el index 08e1a6f93e..59c3bbc76e 100644 --- a/lisp/gnus/gnus-art.el +++ b/lisp/gnus/gnus-art.el @@ -2659,7 +2659,8 @@ If PROMPT (the prefix), prompt for a coding system to use." (dolist (header (mail-header-parse-addresses addresses t)) (when-let* ((address (car (ignore-errors (mail-header-parse-address header)))) - (warning (textsec-suspicious-p address 'email-address))) + (warning (and (string-match "@" address) + (textsec-suspicious-p address 'email-address)))) (goto-char (point-min)) (while (search-forward address nil t) (put-text-property (match-beginning 0) (match-end 0) commit 5d40e1be7e9b0dd2238dedb74125eb7a40229e53 Author: Lars Ingebrigtsen Date: Mon Jan 31 16:24:25 2022 +0100 Clarify that INSTALL isn't for Git checkouts (bug#53627) diff --git a/INSTALL b/INSTALL index 7cb7e0526a..b1e3c72c4b 100644 --- a/INSTALL +++ b/INSTALL @@ -4,11 +4,13 @@ Inc. See the end of the file for license conditions. -This file contains general information on building GNU Emacs. -For more information specific to the MS-Windows, GNUstep/macOS, and -MS-DOS ports, also read the files nt/INSTALL, nextstep/INSTALL, and -msdos/INSTALL. For information about building from a repository checkout -(rather than a release), also read the file INSTALL.REPO. +This file contains general information on building GNU Emacs. For +more information specific to the MS-Windows, GNUstep/macOS, and MS-DOS +ports, also read the files nt/INSTALL, nextstep/INSTALL, and +msdos/INSTALL. + +For information about building from a Git checkout (rather than an +Emacs release), read the INSTALL.REPO file first. BASIC INSTALLATION commit 3ca32105d2bd88120e2ecf9a28febc6c78b3eb0d Author: Michael Albinus Date: Mon Jan 31 15:26:06 2022 +0100 Extend filelock-tests.el for bug#53207 * test/src/filelock-tests.el (filelock-tests--fixture): Make it a defmacro. Adapt callees. (filelock-tests-unlock-spoiled, filelock-tests-kill-buffer-spoiled): Simplify. (filelock-tests-detect-external-change): New test diff --git a/test/src/filelock-tests.el b/test/src/filelock-tests.el index 21478a1a0f..97642669a0 100644 --- a/test/src/filelock-tests.el +++ b/test/src/filelock-tests.el @@ -31,26 +31,26 @@ (require 'ert-x) (require 'seq) -(defun filelock-tests--fixture (test-function) - "Call TEST-FUNCTION under a test fixture. +(defmacro filelock-tests--fixture (&rest body) + "Call BODY under a test fixture. Create a test directory and a buffer whose `buffer-file-name' and -`buffer-file-truename' are a file within it, then call -TEST-FUNCTION. Finally, delete the buffer and the test -directory." - (ert-with-temp-directory temp-dir - (let ((name (concat (file-name-as-directory temp-dir) - "userfile")) - (create-lockfiles t)) - (with-temp-buffer - (setq buffer-file-name name - buffer-file-truename name) - (unwind-protect - (save-current-buffer - (funcall test-function)) - ;; Set `buffer-file-truename' nil to prevent unlocking, - ;; which might prompt the user and/or signal errors. - (setq buffer-file-name nil - buffer-file-truename nil)))))) +`buffer-file-truename' are a file within it, then call BODY. +Finally, delete the buffer and the test directory." + (declare (debug (body))) + `(ert-with-temp-directory temp-dir + (let ((name (concat (file-name-as-directory temp-dir) + "userfile")) + (create-lockfiles t)) + (with-temp-buffer + (setq buffer-file-name name + buffer-file-truename name) + (unwind-protect + (save-current-buffer + ,@body) + ;; Set `buffer-file-truename' nil to prevent unlocking, + ;; which might prompt the user and/or signal errors. + (setq buffer-file-name nil + buffer-file-truename nil)))))) (defun filelock-tests--make-lock-name (file-name) "Return the lock file name for FILE-NAME. @@ -86,105 +86,132 @@ the case)." (ert-deftest filelock-tests-lock-unlock-no-errors () "Check that locking and unlocking works without error." (filelock-tests--fixture - (lambda () - (should-not (file-locked-p (buffer-file-name))) + (should-not (file-locked-p (buffer-file-name))) - ;; inserting text should lock the buffer's file. - (insert "this locks the buffer's file") - (filelock-tests--should-be-locked) - (unlock-buffer) - (set-buffer-modified-p nil) - (should-not (file-locked-p (buffer-file-name))) + ;; Inserting text should lock the buffer's file. + (insert "this locks the buffer's file") + (filelock-tests--should-be-locked) + (unlock-buffer) + (set-buffer-modified-p nil) + (should-not (file-locked-p (buffer-file-name))) - ;; `set-buffer-modified-p' should lock the buffer's file. - (set-buffer-modified-p t) - (filelock-tests--should-be-locked) - (unlock-buffer) - (should-not (file-locked-p (buffer-file-name))) + ;; `set-buffer-modified-p' should lock the buffer's file. + (set-buffer-modified-p t) + (filelock-tests--should-be-locked) + (unlock-buffer) + (should-not (file-locked-p (buffer-file-name))) - (should-not (file-locked-p (buffer-file-name)))))) + (should-not (file-locked-p (buffer-file-name))))) (ert-deftest filelock-tests-lock-spoiled () - "Check `lock-buffer' ." + "Check `lock-buffer'." (skip-unless (not (eq system-type 'ms-dos))) ; no filelock support (filelock-tests--fixture - (lambda () - (filelock-tests--spoil-lock-file buffer-file-truename) - ;; FIXME: errors when locking a file are ignored; should they be? - (set-buffer-modified-p t) - (filelock-tests--unspoil-lock-file buffer-file-truename) - (should-not (file-locked-p buffer-file-truename))))) + (filelock-tests--spoil-lock-file buffer-file-truename) + ;; FIXME: errors when locking a file are ignored; should they be? + (set-buffer-modified-p t) + (filelock-tests--unspoil-lock-file buffer-file-truename) + (should-not (file-locked-p buffer-file-truename)))) (ert-deftest filelock-tests-file-locked-p-spoiled () "Check that `file-locked-p' fails if the lockfile is \"spoiled\"." (skip-unless (not (eq system-type 'ms-dos))) ; no filelock support (filelock-tests--fixture - (lambda () - (filelock-tests--spoil-lock-file buffer-file-truename) - (let ((err (should-error (file-locked-p (buffer-file-name))))) - (should (equal (seq-subseq err 0 2) - (if (eq system-type 'windows-nt) - '(permission-denied "Testing file lock") - '(file-error "Testing file lock")))))))) + (filelock-tests--spoil-lock-file buffer-file-truename) + (let ((err (should-error (file-locked-p (buffer-file-name))))) + (should (equal (seq-subseq err 0 2) + (if (eq system-type 'windows-nt) + '(permission-denied "Testing file lock") + '(file-error "Testing file lock"))))))) (ert-deftest filelock-tests-unlock-spoiled () "Check that `unlock-buffer' fails if the lockfile is \"spoiled\"." (skip-unless (not (eq system-type 'ms-dos))) ; no filelock support (filelock-tests--fixture - (lambda () - ;; Set the buffer modified with file locking temporarily - ;; disabled. - (let ((create-lockfiles nil)) - (set-buffer-modified-p t)) - (should-not (file-locked-p buffer-file-truename)) - (filelock-tests--spoil-lock-file buffer-file-truename) - - ;; Errors from `unlock-buffer' should call - ;; `userlock--handle-unlock-error' (bug#46397). - (let (errors) - (cl-letf (((symbol-function 'userlock--handle-unlock-error) - (lambda (err) (push err errors)))) - (unlock-buffer)) - (should (consp errors)) - (should (equal - (if (eq system-type 'windows-nt) - '(permission-denied "Unlocking file") - '(file-error "Unlocking file")) - (seq-subseq (car errors) 0 2))) - (should (equal (length errors) 1)))))) + ;; Set the buffer modified with file locking temporarily disabled. + (let ((create-lockfiles nil)) + (set-buffer-modified-p t)) + (should-not (file-locked-p buffer-file-truename)) + (filelock-tests--spoil-lock-file buffer-file-truename) + + ;; Errors from `unlock-buffer' should call + ;; `userlock--handle-unlock-error' (bug#46397). + (cl-letf (((symbol-function 'userlock--handle-unlock-error) + (lambda (err) (signal (car err) (cdr err))))) + (should (equal + (if (eq system-type 'windows-nt) + '(permission-denied "Unlocking file") + '(file-error "Unlocking file")) + (seq-subseq (should-error (unlock-buffer)) 0 2)))))) (ert-deftest filelock-tests-kill-buffer-spoiled () "Check that `kill-buffer' fails if a lockfile is \"spoiled\"." (skip-unless (not (eq system-type 'ms-dos))) ; no filelock support (filelock-tests--fixture - (lambda () - ;; Set the buffer modified with file locking temporarily - ;; disabled. - (let ((create-lockfiles nil)) - (set-buffer-modified-p t)) - (should-not (file-locked-p buffer-file-truename)) - (filelock-tests--spoil-lock-file buffer-file-truename) - - ;; Kill the current buffer. Because the buffer is modified Emacs - ;; will attempt to unlock it. Temporarily bind `yes-or-no-p' to - ;; a function that fakes a "yes" answer for the "Buffer modified; - ;; kill anyway?" prompt. - ;; - ;; File errors from unlocking files should call - ;; `userlock--handle-unlock-error' (bug#46397). - (let (errors) + ;; Set the buffer modified with file locking temporarily disabled. + (let ((create-lockfiles nil)) + (set-buffer-modified-p t)) + (should-not (file-locked-p buffer-file-truename)) + (filelock-tests--spoil-lock-file buffer-file-truename) + + ;; Kill the current buffer. Because the buffer is modified Emacs + ;; will attempt to unlock it. Temporarily bind `yes-or-no-p' to a + ;; function that fakes a "yes" answer for the "Buffer modified; + ;; kill anyway?" prompt. + ;; + ;; File errors from unlocking files should call + ;; `userlock--handle-unlock-error' (bug#46397). + (cl-letf (((symbol-function 'yes-or-no-p) #'always) + ((symbol-function 'userlock--handle-unlock-error) + (lambda (err) (signal (car err) (cdr err))))) + (should (equal + (if (eq system-type 'windows-nt) + '(permission-denied "Unlocking file") + '(file-error "Unlocking file")) + (seq-subseq (should-error (kill-buffer)) 0 2)))))) + +(ert-deftest filelock-tests-detect-external-change () + "Check that an external file modification is reported." + (skip-unless (not (eq system-type 'ms-dos))) ; no filelock support + (skip-unless (executable-find "touch")) + (skip-unless (executable-find "echo")) + (dolist (cl '(t nil)) + (filelock-tests--fixture + (let ((create-lockfiles cl)) + (write-region "foo" nil (buffer-file-name)) + (revert-buffer nil 'noconfirm) + (should-not (file-locked-p (buffer-file-name))) + + ;; Just changing the file modification on disk doesn't hurt, + ;; because file contents in buffer and on disk look equal. + (shell-command (format "touch %s" (buffer-file-name))) + (insert "bar") + (when cl (filelock-tests--should-be-locked)) + + ;; Bug#53207: with `create-lockfiles' nil, saving the buffer + ;; results in a prompt. (cl-letf (((symbol-function 'yes-or-no-p) - (lambda (&rest _) t)) - ((symbol-function 'userlock--handle-unlock-error) - (lambda (err) (push err errors)))) - (kill-buffer)) - (should (consp errors)) - (should (equal - (if (eq system-type 'windows-nt) - '(permission-denied "Unlocking file") - '(file-error "Unlocking file")) - (seq-subseq (car errors) 0 2))) - (should (equal (length errors) 1)))))) + (lambda (_) (ert-fail "Test failed unexpectedly")))) + (save-buffer)) + (should-not (file-locked-p (buffer-file-name))) + + ;; Changing the file contents on disk hurts when buffer is + ;; modified. There shall be a query, which we answer. + ;; *Messages* buffer is checked for prompt. + (shell-command (format "echo bar >>%s" (buffer-file-name))) + (cl-letf (((symbol-function 'read-char-choice) + (lambda (prompt &rest _) (message "%s" prompt) ?y))) + (ert-with-message-capture captured-messages + ;; `ask-user-about-supersession-threat' does not work in + ;; batch mode, let's simulate interactiveness. + (let (noninteractive) + (insert "baz")) + (should (string-match-p + (format + "^%s changed on disk; really edit the buffer\\?" + (file-name-nondirectory (buffer-file-name))) + captured-messages)))) + (when cl (filelock-tests--should-be-locked)))))) (provide 'filelock-tests) ;;; filelock-tests.el ends here commit 6da021fce86a06a97b0bff76f69aa57759533dc9 Author: Po Lu Date: Mon Jan 31 21:12:14 2022 +0800 Fix artifacting on PGTK when bits are copied with an alpha channel * src/pgtkterm.c (x_draw_stretch_glyph_string): Draw background respecting `alpha-background'. (pgtk_copy_bits): Use CAIRO_OPERATOR_SOURCE to draw onto the destination surface. diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 9bb611e4c5..c0b76b077c 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -2381,7 +2381,7 @@ x_draw_stretch_glyph_string (struct glyph_string *s) else { pgtk_fill_rectangle (s->f, color, x, y, w, h, - false); + true); } pgtk_end_cr_clip (s->f); @@ -2966,17 +2966,20 @@ pgtk_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, int x, } static void -pgtk_copy_bits (struct frame *f, cairo_rectangle_t * src_rect, - cairo_rectangle_t * dst_rect) +pgtk_copy_bits (struct frame *f, cairo_rectangle_t *src_rect, + cairo_rectangle_t *dst_rect) { cairo_t *cr; + GdkWindow *window; cairo_surface_t *surface; /* temporary surface */ + window = gtk_widget_get_window (FRAME_GTK_WIDGET (f)); + surface = - cairo_surface_create_similar (FRAME_CR_SURFACE (f), - CAIRO_CONTENT_COLOR_ALPHA, - (int) src_rect->width, - (int) src_rect->height); + gdk_window_create_similar_surface (window, CAIRO_CONTENT_COLOR_ALPHA, + FRAME_CR_SURFACE_DESIRED_WIDTH (f), + FRAME_CR_SURFACE_DESIRED_HEIGHT + (f)); cr = cairo_create (surface); cairo_set_source_surface (cr, FRAME_CR_SURFACE (f), -src_rect->x, @@ -2988,6 +2991,7 @@ pgtk_copy_bits (struct frame *f, cairo_rectangle_t * src_rect, cr = pgtk_begin_cr_clip (f); cairo_set_source_surface (cr, surface, dst_rect->x, dst_rect->y); + cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); cairo_rectangle (cr, dst_rect->x, dst_rect->y, dst_rect->width, dst_rect->height); cairo_clip (cr); commit fd42ba3adb557091d251fc1c72634a20f2cb0db6 Author: Eli Zaretskii Date: Mon Jan 31 15:08:08 2022 +0200 Improve 'latin1-display-ucs-per-lynx' * lisp/international/latin1-disp.el (latin1-display-ucs-per-lynx): Don't judge display-ability of all the characters by testing just one of them. Instead, install an ASCII equivalent of every character that the terminal cannot display. diff --git a/lisp/international/latin1-disp.el b/lisp/international/latin1-disp.el index 96a54cc212..7054077fb0 100644 --- a/lisp/international/latin1-disp.el +++ b/lisp/international/latin1-disp.el @@ -764,2426 +764,2425 @@ turn it off and display Unicode characters literally. The display isn't changed if the display can render Unicode characters." (interactive "p") (if (> arg 0) - (unless (char-displayable-p #x101) ; a with macron - ;; It doesn't look as though we have a Unicode font. - (let ((latin1-display-format "%s")) - (mapc - (lambda (l) - (apply 'latin1-display-char l)) - ;; Table derived by running Lynx on a suitable list of - ;; characters in a utf-8 file, except for some added by - ;; hand at the end. - '((?\Ā "A") - (?\ā "a") - (?\Ă "A") - (?\ă "a") - (?\Ą "A") - (?\ą "a") - (?\Ć "C") - (?\ć "c") - (?\Ĉ "C") - (?\ĉ "c") - (?\Ċ "C") - (?\ċ "c") - (?\Č "C") - (?\č "c") - (?\Ď "D") - (?\ď "d") - (?\Đ "Ð") - (?\đ "d/") - (?\Ē "E") - (?\ē "e") - (?\Ĕ "E") - (?\ĕ "e") - (?\Ė "E") - (?\ė "e") - (?\Ę "E") - (?\ę "e") - (?\Ě "E") - (?\ě "e") - (?\Ĝ "G") - (?\ĝ "g") - (?\Ğ "G") - (?\ğ "g") - (?\Ġ "G") - (?\ġ "g") - (?\Ģ "G") - (?\ģ "g") - (?\Ĥ "H") - (?\ĥ "h") - (?\Ħ "H/") - (?\ħ "H") - (?\Ĩ "I") - (?\ĩ "i") - (?\Ī "I") - (?\ī "i") - (?\Ĭ "I") - (?\ĭ "i") - (?\Į "I") - (?\į "i") - (?\İ "I") - (?\ı "i") - (?\IJ "IJ") - (?\ij "ij") - (?\Ĵ "J") - (?\ĵ "j") - (?\Ķ "K") - (?\ķ "k") - (?\ĸ "kk") - (?\Ĺ "L") - (?\ĺ "l") - (?\Ļ "L") - (?\ļ "l") - (?\Ľ "L") - (?\ľ "l") - (?\Ŀ "L.") - (?\ŀ "l.") - (?\Ł "L/") - (?\ł "l/") - (?\Ń "N") - (?\ń "n") - (?\Ņ "N") - (?\ņ "n") - (?\Ň "N") - (?\ň "n") - (?\ʼn "'n") - (?\Ŋ "NG") - (?\ŋ "N") - (?\Ō "O") - (?\ō "o") - (?\Ŏ "O") - (?\ŏ "o") - (?\Ő "O\"") - (?\ő "o\"") - (?\Œ "OE") - (?\œ "oe") - (?\Ŕ "R") - (?\ŕ "r") - (?\Ŗ "R") - (?\ŗ "r") - (?\Ř "R") - (?\ř "r") - (?\Ś "S") - (?\ś "s") - (?\Ŝ "S") - (?\ŝ "s") - (?\Ş "S") - (?\ş "s") - (?\Š "S") - (?\š "s") - (?\Ţ "T") - (?\ţ "t") - (?\Ť "T") - (?\ť "t") - (?\Ŧ "T/") - (?\ŧ "t/") - (?\Ũ "U") - (?\ũ "u") - (?\Ū "U") - (?\ū "u") - (?\Ŭ "U") - (?\ŭ "u") - (?\Ů "U") - (?\ů "u") - (?\Ű "U\"") - (?\ű "u\"") - (?\Ų "U") - (?\ų "u") - (?\Ŵ "W") - (?\ŵ "w") - (?\Ŷ "Y") - (?\ŷ "y") - (?\Ÿ "Y") - (?\Ź "Z") - (?\ź "z") - (?\Ż "Z") - (?\ż "z") - (?\Ž "Z") - (?\ž "z") - (?\ſ "s1") - (?\Ƈ "C2") - (?\ƈ "c2") - (?\Ƒ "F2") - (?\ƒ " f") - (?\Ƙ "K2") - (?\ƙ "k2") - (?\Ơ "O9") - (?\ơ "o9") - (?\Ƣ "OI") - (?\ƣ "oi") - (?\Ʀ "yr") - (?\Ư "U9") - (?\ư "u9") - (?\Ƶ "Z/") - (?\ƶ "z/") - (?\Ʒ "ED") - (?\Ǎ "A") - (?\ǎ "a") - (?\Ǐ "I") - (?\ǐ "i") - (?\Ǒ "O") - (?\ǒ "o") - (?\Ǔ "U") - (?\ǔ "u") - (?\Ǖ "U:-") - (?\ǖ "u:-") - (?\Ǘ "U:'") - (?\ǘ "u:'") - (?\Ǚ "U:<") - (?\ǚ "u:<") - (?\Ǜ "U:!") - (?\ǜ "u:!") - (?\Ǟ "A1") - (?\ǟ "a1") - (?\Ǡ "A7") - (?\ǡ "a7") - (?\Ǣ "A3") - (?\ǣ "a3") - (?\Ǥ "G/") - (?\ǥ "g/") - (?\Ǧ "G") - (?\ǧ "g") - (?\Ǩ "K") - (?\ǩ "k") - (?\Ǫ "O") - (?\ǫ "o") - (?\Ǭ "O1") - (?\ǭ "o1") - (?\Ǯ "EZ") - (?\ǯ "ez") - (?\ǰ "j") - (?\Ǵ "G") - (?\ǵ "g") - (?\Ǻ "AA'") - (?\ǻ "aa'") - (?\Ǽ "AE'") - (?\ǽ "ae'") - (?\Ǿ "O/'") - (?\ǿ "o/'") - (?\Ȁ "A!!") - (?\ȁ "a!!") - (?\Ȃ "A)") - (?\ȃ "a)") - (?\Ȅ "E!!") - (?\ȅ "e!!") - (?\Ȇ "E)") - (?\ȇ "e)") - (?\Ȉ "I!!") - (?\ȉ "i!!") - (?\Ȋ "I)") - (?\ȋ "i)") - (?\Ȍ "O!!") - (?\ȍ "o!!") - (?\Ȏ "O)") - (?\ȏ "o)") - (?\Ȑ "R!!") - (?\ȑ "r!!") - (?\Ȓ "R)") - (?\ȓ "r)") - (?\Ȕ "U!!") - (?\ȕ "u!!") - (?\Ȗ "U)") - (?\ȗ "u)") - (?\ȝ "Z") - (?\ɑ "A") - (?\ɒ "A.") - (?\ɓ "b`") - (?\ɔ "O") - (?\ɖ "d.") - (?\ɗ "d`") - (?\ɘ "@") - (?\ə "@") - (?\ɚ "R") - (?\ɛ "E") - (?\ɜ "V\"") - (?\ɝ "R") - (?\ɞ "O\"") - (?\ɟ "J") - (?\ɠ "g`") - (?\ɡ "g") - (?\ɢ "G") - (?\ɣ "Q") - (?\ɤ "o-") - (?\ɥ "j") - (?\ɦ "h") - (?\ɨ "i\"") - (?\ɩ "I") - (?\ɪ "I") - (?\ɫ "L") - (?\ɬ "L") - (?\ɭ "l.") - (?\ɮ "z") - (?\ɯ "u-") - (?\ɰ "j") - (?\ɱ "M") - (?\ɳ "n.") - (?\ɴ "n\"") - (?\ɵ "@.") - (?\ɶ "&.") - (?\ɷ "U") - (?\ɹ "r") - (?\ɺ "*") - (?\ɻ "r.") - (?\ɽ "*.") - (?\ɾ "*") - (?\ʀ "R") - (?\ʁ "g\"") - (?\ʂ "s.") - (?\ʃ "S") - (?\ʄ "J`") - (?\ʇ "t!") - (?\ʈ "t.") - (?\ʉ "u\"") - (?\ʊ "U") - (?\ʋ "r") - (?\ʌ "V") - (?\ʍ "w") - (?\ʎ "l^") - (?\ʏ "I.") - (?\ʐ "z.") - (?\ʒ "Z") - (?\ʔ "?") - (?\ʕ "H") - (?\ʖ "l!") - (?\ʗ "c!") - (?\ʘ "p!") - (?\ʙ "b") - (?\ʛ "G`") - (?\ʝ "j") - (?\ʞ "k!") - (?\ʟ "L") - (?\ʠ "q`") - (?\ʤ "d3") - (?\ʦ "ts") - (?\ʧ "tS") - (?\ʰ "") - (?\ʱ "") - (?\ʲ ";") - (?\ʳ "") - (?\ʷ "") - (?\ʻ ";S") - (?\ʼ "`") - (?\ˆ "^") - (?\ˇ "'<") - (?\ˈ "|") - (?\ˉ "1-") - (?\ˋ "1!") - (?\ː ":") - (?\ˑ ":\\") - (?\˖ "+") - (?\˗ "-") - (?\˘ "'(") - (?\˙ "'.") - (?\˚ "'0") - (?\˛ "';") - (?\˜ "~") - (?\˝ "'\"") - (?\˥ "_T") - (?\˦ "_H") - (?\˧ "_M") - (?\˨ "_L") - (?\˩ "_B") - (?\ˬ "_v") - (?\ˮ "''") - (?\̀ "`") - (?\́ "'") - (?\̂ "^") - (?\̃ "~") - (?\̄ "¯") - (?\̇ "·") - (?\̈ "¨") - (?\̊ "°") - (?\̋ "''") - (?\̍ "|") - (?\̎ "||") - (?\̏ "``") - (?\̡ ";") - (?\̢ ".") - (?\̣ ".") - (?\̤ "") - (?\̥ "") - (?\̦ ",") - (?\̧ "¸") - (?\̩ "-") - (?\̪ "[") - (?\̫ "") - (?\̴ "~") - (?\̷ "/") - (?\̸ "/") - (?\̀ "`") - (?\́ "'") - (?\͂ "~") - (?\̈́ "'%") - (?\ͅ "j3") - (?\͇ "=") - (?\͠ "~~") - (?\ʹ "'") - (?\͵ ",") - (?\ͺ "j3") - (?\; "?%") - (?\΄ "'*") - (?\΅ "'%") - (?\Ά "A'") - (?\· "·") - (?\Έ "E'") - (?\Ή "Y%") - (?\Ί "I'") - (?\Ό "O'") - (?\Ύ "U%") - (?\Ώ "W%") - (?\ΐ "i3") - (?\Α "A") - (?\Β "B") - (?\Γ "G") - (?\Δ "D") - (?\Ε "E") - (?\Ζ "Z") - (?\Η "Y") - (?\Θ "TH") - (?\Ι "I") - (?\Κ "K") - (?\Λ "L") - (?\Μ "M") - (?\Ν "N") - (?\Ξ "C") - (?\Ο "O") - (?\Π "P") - (?\Ρ "R") - (?\Σ "S") - (?\Τ "T") - (?\Υ "U") - (?\Φ "F") - (?\Χ "X") - (?\Ψ "Q") - (?\Ω "W*") - (?\Ϊ "J") - (?\Ϋ "V*") - (?\ά "a'") - (?\έ "e'") - (?\ή "y%") - (?\ί "i'") - (?\ΰ "u3") - (?\α "a") - (?\β "b") - (?\γ "g") - (?\δ "d") - (?\ε "e") - (?\ζ "z") - (?\η "y") - (?\θ "th") - (?\ι "i") - (?\κ "k") - (?\λ "l") - (?\μ "µ") - (?\ν "n") - (?\ξ "c") - (?\ο "o") - (?\π "p") - (?\ρ "r") - (?\ς "*s") - (?\σ "s") - (?\τ "t") - (?\υ "u") - (?\φ "f") - (?\χ "x") - (?\ψ "q") - (?\ω "w") - (?\ϊ "j") - (?\ϋ "v*") - (?\ό "o'") - (?\ύ "u%") - (?\ώ "w%") - (?\ϐ "beta ") - (?\ϑ "theta ") - (?\ϒ "upsi ") - (?\ϕ "phi ") - (?\ϖ "pi ") - (?\ϗ "k.") - (?\Ϛ "T3") - (?\ϛ "t3") - (?\Ϝ "M3") - (?\ϝ "m3") - (?\Ϟ "K3") - (?\ϟ "k3") - (?\Ϡ "P3") - (?\ϡ "p3") - (?\ϰ "kappa ") - (?\ϱ "rho ") - (?\ϳ "J") - (?\ϴ "'%") - (?\ϵ "j3") - (?\Ё "IO") - (?\Ђ "D%") - (?\Ѓ "G%") - (?\Є "IE") - (?\Ѕ "DS") - (?\І "II") - (?\Ї "YI") - (?\Ј "J%") - (?\Љ "LJ") - (?\Њ "NJ") - (?\Ћ "Ts") - (?\Ќ "KJ") - (?\Ў "V%") - (?\Џ "DZ") - (?\А "A") - (?\Б "B") - (?\В "V") - (?\Г "G") - (?\Д "D") - (?\Е "E") - (?\Ж "ZH") - (?\З "Z") - (?\И "I") - (?\Й "J") - (?\К "K") - (?\Л "L") - (?\М "M") - (?\Н "N") - (?\О "O") - (?\П "P") - (?\Р "R") - (?\С "S") - (?\Т "T") - (?\У "U") - (?\Ф "F") - (?\Х "H") - (?\Ц "C") - (?\Ч "CH") - (?\Ш "SH") - (?\Щ "SCH") - (?\Ъ "\"") - (?\Ы "Y") - (?\Ь "'") - (?\Э "`E") - (?\Ю "YU") - (?\Я "YA") - (?\а "a") - (?\б "b") - (?\в "v") - (?\г "g") - (?\д "d") - (?\е "e") - (?\ж "zh") - (?\з "z") - (?\и "i") - (?\й "j") - (?\к "k") - (?\л "l") - (?\м "m") - (?\н "n") - (?\о "o") - (?\п "p") - (?\р "r") - (?\с "s") - (?\т "t") - (?\у "u") - (?\ф "f") - (?\х "h") - (?\ц "c") - (?\ч "ch") - (?\ш "sh") - (?\щ "sch") - (?\ъ "\"") - (?\ы "y") - (?\ь "'") - (?\э "`e") - (?\ю "yu") - (?\я "ya") - (?\ё "io") - (?\ђ "d%") - (?\ѓ "g%") - (?\є "ie") - (?\ѕ "ds") - (?\і "ii") - (?\ї "yi") - (?\ј "j%") - (?\љ "lj") - (?\њ "nj") - (?\ћ "ts") - (?\ќ "kj") - (?\ў "v%") - (?\џ "dz") - (?\Ѣ "Y3") - (?\ѣ "y3") - (?\Ѫ "O3") - (?\ѫ "o3") - (?\Ѳ "F3") - (?\ѳ "f3") - (?\Ѵ "V3") - (?\ѵ "v3") - (?\Ҁ "C3") - (?\ҁ "c3") - (?\Ґ "G3") - (?\ґ "g3") - (?\Ӕ "AE") - (?\ӕ "ae") - (?\ִ "i") - (?\ַ "a") - (?\ָ "o") - (?\ּ "u") - (?\ֿ "h") - (?\ׂ ":") - (?\א "#") - (?\ב "B+") - (?\ג "G+") - (?\ד "D+") - (?\ה "H+") - (?\ו "W+") - (?\ז "Z+") - (?\ח "X+") - (?\ט "Tj") - (?\י "J+") - (?\ך "K%") - (?\כ "K+") - (?\ל "L+") - (?\ם "M%") - (?\מ "M+") - (?\ן "N%") - (?\נ "N+") - (?\ס "S+") - (?\ע "E+") - (?\ף "P%") - (?\פ "P+") - (?\ץ "Zj") - (?\צ "ZJ") - (?\ק "Q+") - (?\ר "R+") - (?\ש "Sh") - (?\ת "T+") - (?\װ "v") - (?\ױ "oy") - (?\ײ "ey") - (?\، ",+") - (?\؛ ";+") - (?\؟ "?+") - (?\ء "H'") - (?\آ "aM") - (?\أ "aH") - (?\ؤ "wH") - (?\إ "ah") - (?\ئ "yH") - (?\ا "a+") - (?\ب "b+") - (?\ة "tm") - (?\ت "t+") - (?\ث "tk") - (?\ج "g+") - (?\ح "hk") - (?\خ "x+") - (?\د "d+") - (?\ذ "dk") - (?\ر "r+") - (?\ز "z+") - (?\س "s+") - (?\ش "sn") - (?\ص "c+") - (?\ض "dd") - (?\ط "tj") - (?\ظ "zH") - (?\ع "e+") - (?\غ "i+") - (?\ـ "++") - (?\ف "f+") - (?\ق "q+") - (?\ك "k+") - (?\ل "l+") - (?\م "m+") - (?\ن "n+") - (?\ه "h+") - (?\و "w+") - (?\ى "j+") - (?\ي "y+") - (?\ً ":+") - (?\ٌ "\"+") - (?\ٍ "=+") - (?\َ "/+") - (?\ُ "'+") - (?\ِ "1+") - (?\ّ "3+") - (?\ْ "0+") - (?\٠ "0a") - (?\١ "1a") - (?\٢ "2a") - (?\٣ "3a") - (?\٤ "4a") - (?\٥ "5a") - (?\٦ "6a") - (?\٧ "7a") - (?\٨ "8a") - (?\٩ "9a") - (?\ٰ "aS") - (?\پ "p+") - (?\ځ "hH") - (?\چ "tc") - (?\ژ "zj") - (?\ڤ "v+") - (?\گ "gf") - (?\۰ "0a") - (?\۱ "1a") - (?\۲ "2a") - (?\۳ "3a") - (?\۴ "4a") - (?\۵ "5a") - (?\۶ "6a") - (?\۷ "7a") - (?\۸ "8a") - (?\۹ "9a") - (?\ሀ "he") - (?\ሁ "hu") - (?\ሂ "hi") - (?\ሃ "ha") - (?\ሄ "hE") - (?\ህ "h") - (?\ሆ "ho") - (?\ለ "le") - (?\ሉ "lu") - (?\ሊ "li") - (?\ላ "la") - (?\ሌ "lE") - (?\ል "l") - (?\ሎ "lo") - (?\ሏ "lWa") - (?\ሐ "He") - (?\ሑ "Hu") - (?\ሒ "Hi") - (?\ሓ "Ha") - (?\ሔ "HE") - (?\ሕ "H") - (?\ሖ "Ho") - (?\ሗ "HWa") - (?\መ "me") - (?\ሙ "mu") - (?\ሚ "mi") - (?\ማ "ma") - (?\ሜ "mE") - (?\ም "m") - (?\ሞ "mo") - (?\ሟ "mWa") - (?\ሠ "`se") - (?\ሡ "`su") - (?\ሢ "`si") - (?\ሣ "`sa") - (?\ሤ "`sE") - (?\ሥ "`s") - (?\ሦ "`so") - (?\ሧ "`sWa") - (?\ረ "re") - (?\ሩ "ru") - (?\ሪ "ri") - (?\ራ "ra") - (?\ሬ "rE") - (?\ር "r") - (?\ሮ "ro") - (?\ሯ "rWa") - (?\ሰ "se") - (?\ሱ "su") - (?\ሲ "si") - (?\ሳ "sa") - (?\ሴ "sE") - (?\ስ "s") - (?\ሶ "so") - (?\ሷ "sWa") - (?\ሸ "xe") - (?\ሹ "xu") - (?\ሺ "xi") - (?\ሻ "xa") - (?\ሼ "xE") - (?\ሽ "xa") - (?\ሾ "xo") - (?\ሿ "xWa") - (?\ቀ "qe") - (?\ቁ "qu") - (?\ቂ "qi") - (?\ቃ "qa") - (?\ቄ "qE") - (?\ቅ "q") - (?\ቆ "qo") - (?\ቈ "qWe") - (?\ቊ "qWi") - (?\ቋ "qWa") - (?\ቌ "qWE") - (?\ቍ "qW") - (?\ቐ "Qe") - (?\ቑ "Qu") - (?\ቒ "Qi") - (?\ቓ "Qa") - (?\ቔ "QE") - (?\ቕ "Q") - (?\ቖ "Qo") - (?\ቘ "QWe") - (?\ቚ "QWi") - (?\ቛ "QWa") - (?\ቜ "QWE") - (?\ቝ "QW") - (?\በ "be") - (?\ቡ "bu") - (?\ቢ "bi") - (?\ባ "ba") - (?\ቤ "bE") - (?\ብ "b") - (?\ቦ "bo") - (?\ቧ "bWa") - (?\ቨ "ve") - (?\ቩ "vu") - (?\ቪ "vi") - (?\ቫ "va") - (?\ቬ "vE") - (?\ቭ "v") - (?\ቮ "vo") - (?\ቯ "vWa") - (?\ተ "te") - (?\ቱ "tu") - (?\ቲ "ti") - (?\ታ "ta") - (?\ቴ "tE") - (?\ት "t") - (?\ቶ "to") - (?\ቷ "tWa") - (?\ቸ "ce") - (?\ቹ "cu") - (?\ቺ "ci") - (?\ቻ "ca") - (?\ቼ "cE") - (?\ች "c") - (?\ቾ "co") - (?\ቿ "cWa") - (?\ኀ "`he") - (?\ኁ "`hu") - (?\ኂ "`hi") - (?\ኃ "`ha") - (?\ኄ "`hE") - (?\ኅ "`h") - (?\ኆ "`ho") - (?\ኈ "hWe") - (?\ኊ "hWi") - (?\ኋ "hWa") - (?\ኌ "hWE") - (?\ኍ "hW") - (?\ነ "na") - (?\ኑ "nu") - (?\ኒ "ni") - (?\ና "na") - (?\ኔ "nE") - (?\ን "n") - (?\ኖ "no") - (?\ኗ "nWa") - (?\ኘ "Ne") - (?\ኙ "Nu") - (?\ኚ "Ni") - (?\ኛ "Na") - (?\ኜ "NE") - (?\ኝ "N") - (?\ኞ "No") - (?\ኟ "NWa") - (?\አ "e") - (?\ኡ "u") - (?\ኢ "i") - (?\ኣ "a") - (?\ኤ "E") - (?\እ "I") - (?\ኦ "o") - (?\ኧ "e3") - (?\ከ "ke") - (?\ኩ "ku") - (?\ኪ "ki") - (?\ካ "ka") - (?\ኬ "kE") - (?\ክ "k") - (?\ኮ "ko") - (?\ኰ "kWe") - (?\ኲ "kWi") - (?\ኳ "kWa") - (?\ኴ "kWE") - (?\ኵ "kW") - (?\ኸ "Ke") - (?\ኹ "Ku") - (?\ኺ "Ki") - (?\ኻ "Ka") - (?\ኼ "KE") - (?\ኽ "K") - (?\ኾ "Ko") - (?\ዀ "KWe") - (?\ዂ "KWi") - (?\ዃ "KWa") - (?\ዄ "KWE") - (?\ዅ "KW") - (?\ወ "we") - (?\ዉ "wu") - (?\ዊ "wi") - (?\ዋ "wa") - (?\ዌ "wE") - (?\ው "w") - (?\ዎ "wo") - (?\ዐ "`e") - (?\ዑ "`u") - (?\ዒ "`i") - (?\ዓ "`a") - (?\ዔ "`E") - (?\ዕ "`I") - (?\ዖ "`o") - (?\ዘ "ze") - (?\ዙ "zu") - (?\ዚ "zi") - (?\ዛ "za") - (?\ዜ "zE") - (?\ዝ "z") - (?\ዞ "zo") - (?\ዟ "zWa") - (?\ዠ "Ze") - (?\ዡ "Zu") - (?\ዢ "Zi") - (?\ዣ "Za") - (?\ዤ "ZE") - (?\ዥ "Z") - (?\ዦ "Zo") - (?\ዧ "ZWa") - (?\የ "ye") - (?\ዩ "yu") - (?\ዪ "yi") - (?\ያ "ya") - (?\ዬ "yE") - (?\ይ "y") - (?\ዮ "yo") - (?\ዯ "yWa") - (?\ደ "de") - (?\ዱ "du") - (?\ዲ "di") - (?\ዳ "da") - (?\ዴ "dE") - (?\ድ "d") - (?\ዶ "do") - (?\ዷ "dWa") - (?\ዸ "De") - (?\ዹ "Du") - (?\ዺ "Di") - (?\ዻ "Da") - (?\ዼ "DE") - (?\ዽ "D") - (?\ዾ "Do") - (?\ዿ "DWa") - (?\ጀ "je") - (?\ጁ "ju") - (?\ጂ "ji") - (?\ጃ "ja") - (?\ጄ "jE") - (?\ጅ "j") - (?\ጆ "jo") - (?\ጇ "jWa") - (?\ገ "ga") - (?\ጉ "gu") - (?\ጊ "gi") - (?\ጋ "ga") - (?\ጌ "gE") - (?\ግ "g") - (?\ጎ "go") - (?\ጐ "gWu") - (?\ጒ "gWi") - (?\ጓ "gWa") - (?\ጔ "gWE") - (?\ጕ "gW") - (?\ጘ "Ge") - (?\ጙ "Gu") - (?\ጚ "Gi") - (?\ጛ "Ga") - (?\ጜ "GE") - (?\ጝ "G") - (?\ጞ "Go") - (?\ጟ "GWa") - (?\ጠ "Te") - (?\ጡ "Tu") - (?\ጢ "Ti") - (?\ጣ "Ta") - (?\ጤ "TE") - (?\ጥ "T") - (?\ጦ "To") - (?\ጧ "TWa") - (?\ጨ "Ce") - (?\ጩ "Ca") - (?\ጪ "Cu") - (?\ጫ "Ca") - (?\ጬ "CE") - (?\ጭ "C") - (?\ጮ "Co") - (?\ጯ "CWa") - (?\ጰ "Pe") - (?\ጱ "Pu") - (?\ጲ "Pi") - (?\ጳ "Pa") - (?\ጴ "PE") - (?\ጵ "P") - (?\ጶ "Po") - (?\ጷ "PWa") - (?\ጸ "SWe") - (?\ጹ "SWu") - (?\ጺ "SWi") - (?\ጻ "SWa") - (?\ጼ "SWE") - (?\ጽ "SW") - (?\ጾ "SWo") - (?\ጿ "SWa") - (?\ፀ "`Sa") - (?\ፁ "`Su") - (?\ፂ "`Si") - (?\ፃ "`Sa") - (?\ፄ "`SE") - (?\ፅ "`S") - (?\ፆ "`So") - (?\ፈ "fa") - (?\ፉ "fu") - (?\ፊ "fi") - (?\ፋ "fa") - (?\ፌ "fE") - (?\ፍ "o") - (?\ፎ "fo") - (?\ፏ "fWa") - (?\ፐ "pe") - (?\ፑ "pu") - (?\ፒ "pi") - (?\ፓ "pa") - (?\ፔ "pE") - (?\ፕ "p") - (?\ፖ "po") - (?\ፗ "pWa") - (?\ፘ "mYa") - (?\ፙ "rYa") - (?\ፚ "fYa") - (?\፠ " ") - (?\፡ ":") - (?\። "::") - (?\፣ ",") - (?\፤ ";") - (?\፥ "-:") - (?\፦ ":-") - (?\፧ "`?") - (?\፨ ":|:") - (?\፩ "`1") - (?\፪ "`2") - (?\፫ "`3") - (?\፬ "`4") - (?\፭ "`5") - (?\፮ "`6") - (?\፯ "`7") - (?\፰ "`8") - (?\፱ "`9") - (?\፲ "`10") - (?\፳ "`20") - (?\፴ "`30") - (?\፵ "`40") - (?\፶ "`50") - (?\፷ "`60") - (?\፸ "`70") - (?\፹ "`80") - (?\፺ "`90") - (?\፻ "`100") - (?\፼ "`10000") - (?\Ḁ "A-0") - (?\ḁ "a-0") - (?\Ḃ "B.") - (?\ḃ "b.") - (?\Ḅ "B-.") - (?\ḅ "b-.") - (?\Ḇ "B_") - (?\ḇ "b_") - (?\Ḉ "C,'") - (?\ḉ "c,'") - (?\Ḋ "D.") - (?\ḋ "d.") - (?\Ḍ "D-.") - (?\ḍ "d-.") - (?\Ḏ "D_") - (?\ḏ "d_") - (?\Ḑ "D,") - (?\ḑ "d,") - (?\Ḓ "D->") - (?\ḓ "d->") - (?\Ḕ "E-!") - (?\ḕ "e-!") - (?\Ḗ "E-'") - (?\ḗ "e-'") - (?\Ḙ "E->") - (?\ḙ "e->") - (?\Ḛ "E-?") - (?\ḛ "e-?") - (?\Ḝ "E,(") - (?\ḝ "e,(") - (?\Ḟ "F.") - (?\ḟ "f.") - (?\Ḡ "G-") - (?\ḡ "g-") - (?\Ḣ "H.") - (?\ḣ "h.") - (?\Ḥ "H-.") - (?\ḥ "h-.") - (?\Ḧ "H:") - (?\ḧ "h:") - (?\Ḩ "H,") - (?\ḩ "h,") - (?\Ḫ "H-(") - (?\ḫ "h-(") - (?\Ḭ "I-?") - (?\ḭ "i-?") - (?\Ḯ "I:'") - (?\ḯ "i:'") - (?\Ḱ "K'") - (?\ḱ "k'") - (?\Ḳ "K-.") - (?\ḳ "k-.") - (?\Ḵ "K_") - (?\ḵ "k_") - (?\Ḷ "L-.") - (?\ḷ "l-.") - (?\Ḹ "L--.") - (?\ḹ "l--.") - (?\Ḻ "L_") - (?\ḻ "l_") - (?\Ḽ "L->") - (?\ḽ "l->") - (?\Ḿ "M'") - (?\ḿ "m'") - (?\Ṁ "M.") - (?\ṁ "m.") - (?\Ṃ "M-.") - (?\ṃ "m-.") - (?\Ṅ "N.") - (?\ṅ "n.") - (?\Ṇ "N-.") - (?\ṇ "n-.") - (?\Ṉ "N_") - (?\ṉ "n_") - (?\Ṋ "N->") - (?\ṋ "n->") - (?\Ṍ "O?'") - (?\ṍ "o?'") - (?\Ṏ "O?:") - (?\ṏ "o?:") - (?\Ṑ "O-!") - (?\ṑ "o-!") - (?\Ṓ "O-'") - (?\ṓ "o-'") - (?\Ṕ "P'") - (?\ṕ "p'") - (?\Ṗ "P.") - (?\ṗ "p.") - (?\Ṙ "R.") - (?\ṙ "r.") - (?\Ṛ "R-.") - (?\ṛ "r-.") - (?\Ṝ "R--.") - (?\ṝ "r--.") - (?\Ṟ "R_") - (?\ṟ "r_") - (?\Ṡ "S.") - (?\ṡ "s.") - (?\Ṣ "S-.") - (?\ṣ "s-.") - (?\Ṥ "S'.") - (?\ṥ "s'.") - (?\Ṧ "S<.") - (?\ṧ "s<.") - (?\Ṩ "S.-.") - (?\ṩ "s.-.") - (?\Ṫ "T.") - (?\ṫ "t.") - (?\Ṭ "T-.") - (?\ṭ "t-.") - (?\Ṯ "T_") - (?\ṯ "t_") - (?\Ṱ "T->") - (?\ṱ "t->") - (?\Ṳ "U--:") - (?\ṳ "u--:") - (?\Ṵ "U-?") - (?\ṵ "u-?") - (?\Ṷ "U->") - (?\ṷ "u->") - (?\Ṹ "U?'") - (?\ṹ "u?'") - (?\Ṻ "U-:") - (?\ṻ "u-:") - (?\Ṽ "V?") - (?\ṽ "v?") - (?\Ṿ "V-.") - (?\ṿ "v-.") - (?\Ẁ "W!") - (?\ẁ "w!") - (?\Ẃ "W'") - (?\ẃ "w'") - (?\Ẅ "W:") - (?\ẅ "w:") - (?\Ẇ "W.") - (?\ẇ "w.") - (?\Ẉ "W-.") - (?\ẉ "w-.") - (?\Ẋ "X.") - (?\ẋ "x.") - (?\Ẍ "X:") - (?\ẍ "x:") - (?\Ẏ "Y.") - (?\ẏ "y.") - (?\Ẑ "Z>") - (?\ẑ "z>") - (?\Ẓ "Z-.") - (?\ẓ "z-.") - (?\Ẕ "Z_") - (?\ẕ "z_") - (?\ẖ "h_") - (?\ẗ "t:") - (?\ẘ "w0") - (?\ẙ "y0") - (?\Ạ "A-.") - (?\ạ "a-.") - (?\Ả "A2") - (?\ả "a2") - (?\Ấ "A>'") - (?\ấ "a>'") - (?\Ầ "A>!") - (?\ầ "a>!") - (?\Ẩ "A>2") - (?\ẩ "a>2") - (?\Ẫ "A>?") - (?\ẫ "a>?") - (?\Ậ "A>-.") - (?\ậ "a>-.") - (?\Ắ "A('") - (?\ắ "a('") - (?\Ằ "A(!") - (?\ằ "a(!") - (?\Ẳ "A(2") - (?\ẳ "a(2") - (?\Ẵ "A(?") - (?\ẵ "a(?") - (?\Ặ "A(-.") - (?\ặ "a(-.") - (?\Ẹ "E-.") - (?\ẹ "e-.") - (?\Ẻ "E2") - (?\ẻ "e2") - (?\Ẽ "E?") - (?\ẽ "e?") - (?\Ế "E>'") - (?\ế "e>'") - (?\Ề "E>!") - (?\ề "e>!") - (?\Ể "E>2") - (?\ể "e>2") - (?\Ễ "E>?") - (?\ễ "e>?") - (?\Ệ "E>-.") - (?\ệ "e>-.") - (?\Ỉ "I2") - (?\ỉ "i2") - (?\Ị "I-.") - (?\ị "i-.") - (?\Ọ "O-.") - (?\ọ "o-.") - (?\Ỏ "O2") - (?\ỏ "o2") - (?\Ố "O>'") - (?\ố "o>'") - (?\Ồ "O>!") - (?\ồ "o>!") - (?\Ổ "O>2") - (?\ổ "o>2") - (?\Ỗ "O>?") - (?\ỗ "o>?") - (?\Ộ "O>-.") - (?\ộ "o>-.") - (?\Ớ "O9'") - (?\ớ "o9'") - (?\Ờ "O9!") - (?\ờ "o9!") - (?\Ở "O92") - (?\ở "o92") - (?\Ỡ "O9?") - (?\ỡ "o9?") - (?\Ợ "O9-.") - (?\ợ "o9-.") - (?\Ụ "U-.") - (?\ụ "u-.") - (?\Ủ "U2") - (?\ủ "u2") - (?\Ứ "U9'") - (?\ứ "u9'") - (?\Ừ "U9!") - (?\ừ "u9!") - (?\Ử "U92") - (?\ử "u92") - (?\Ữ "U9?") - (?\ữ "u9?") - (?\Ự "U9-.") - (?\ự "u9-.") - (?\Ỳ "Y!") - (?\ỳ "y!") - (?\Ỵ "Y-.") - (?\ỵ "y-.") - (?\Ỷ "Y2") - (?\ỷ "y2") - (?\Ỹ "Y?") - (?\ỹ "y?") - (?\ἀ "a") - (?\ἁ "ha") - (?\ἂ "`a") - (?\ἃ "h`a") - (?\ἄ "a'") - (?\ἅ "ha'") - (?\ἆ "a~") - (?\ἇ "ha~") - (?\Ἀ "A") - (?\Ἁ "hA") - (?\Ἂ "`A") - (?\Ἃ "h`A") - (?\Ἄ "A'") - (?\Ἅ "hA'") - (?\Ἆ "A~") - (?\Ἇ "hA~") - (?\ἑ "he") - (?\Ἑ "hE") - (?\ἱ "hi") - (?\Ἱ "hI") - (?\ὁ "ho") - (?\Ὁ "hO") - (?\ὑ "hu") - (?\Ὑ "hU") - (?\᾿ ",,") - (?\῀ "?*") - (?\῁ "?:") - (?\῍ ",!") - (?\῎ ",'") - (?\῏ "?,") - (?\῝ ";!") - (?\῞ ";'") - (?\῟ "?;") - (?\ῥ "rh") - (?\Ῥ "Rh") - (?\῭ "!:") - (?\` "!*") - (?\῾ ";;") - (?\  " ") - (?\  " ") - (?\  " ") - (?\  " ") - (?\  " ") - (?\  " ") - (?\  " ") - (?\  " ") - (?\  " ") - (?\  " ") - (?\‐ "-") - (?\‑ "-") - (?\– "-") - (?\— "--") - (?\― "-") - (?\‖ "||") - (?\‗ "=2") - (?\‘ "`") - (?\’ "'") - (?\‚ "'") - (?\‛ "'") - (?\“ "\"") - (?\” "\"") - (?\„ "\"") - (?\‟ "\"") - (?\† "/-") - (?\‡ "/=") - (?\• " o ") - (?\․ ".") - (?\‥ "..") - (?\… "...") - (?\‧ "·") - (?\‰ " 0/00") - (?\′ "'") - (?\″ "''") - (?\‴ "'''") - (?\‵ "`") - (?\‶ "``") - (?\‷ "```") - (?\‸ "Ca") - (?\‹ "<") - (?\› ">") - (?\※ ":X") - (?\‼ "!!") - (?\‾ "'-") - (?\⁃ "-") - (?\⁄ "/") - (?\⁈ "?!") - (?\⁉ "!?") - (?\⁰ "^0") - (?\⁴ "^4") - (?\⁵ "^5") - (?\⁶ "^6") - (?\⁷ "^7") - (?\⁸ "^8") - (?\⁹ "^9") - (?\⁺ "^+") - (?\⁻ "^-") - (?\⁼ "^=") - (?\⁽ "^(") - (?\⁾ "^)") - (?\ⁿ "^n") - (?\₀ "_0") - (?\₁ "_1") - (?\₂ "_2") - (?\₃ "_3") - (?\₄ "_4") - (?\₅ "_5") - (?\₆ "_6") - (?\₇ "_7") - (?\₈ "_8") - (?\₉ "_9") - (?\₊ "_+") - (?\₋ "_-") - (?\₌ "_=") - (?\₍ "(") - (?\₎ ")") - (?\₣ "Ff") - (?\₤ "Li") - (?\₧ "Pt") - (?\₩ "W=") - (?\€ "EUR") - (?\℀ "a/c") - (?\℁ "a/s") - (?\℃ "oC") - (?\℅ "c/o") - (?\℆ "c/u") - (?\℉ "oF") - (?\ℊ "g") - (?\ℎ "h") - (?\ℏ "\\hbar") - (?\ℑ "Im") - (?\ℓ "l") - (?\№ "No.") - (?\℗ "PO") - (?\℘ "P") - (?\ℜ "Re") - (?\℞ "Rx") - (?\℠ "(SM)") - (?\℡ "TEL") - (?\™ "(TM)") - (?\Ω "Ohm") - (?\K "K") - (?\Å "Ang.") - (?\℮ "est.") - (?\ℴ "o") - (?\ℵ "Aleph ") - (?\ℶ "Bet ") - (?\ℷ "Gimel ") - (?\ℸ "Dalet ") - (?\⅓ " 1/3") - (?\⅔ " 2/3") - (?\⅕ " 1/5") - (?\⅖ " 2/5") - (?\⅗ " 3/5") - (?\⅘ " 4/5") - (?\⅙ " 1/6") - (?\⅚ " 5/6") - (?\⅛ " 1/8") - (?\⅜ " 3/8") - (?\⅝ " 5/8") - (?\⅞ " 7/8") - (?\⅟ " 1/") - (?\Ⅰ "I") - (?\Ⅱ "II") - (?\Ⅲ "III") - (?\Ⅳ "IV") - (?\Ⅴ "V") - (?\Ⅵ "VI") - (?\Ⅶ "VII") - (?\Ⅷ "VIII") - (?\Ⅸ "IX") - (?\Ⅹ "X") - (?\Ⅺ "XI") - (?\Ⅻ "XII") - (?\Ⅼ "L") - (?\Ⅽ "C") - (?\Ⅾ "D") - (?\Ⅿ "M") - (?\ⅰ "i") - (?\ⅱ "ii") - (?\ⅲ "iii") - (?\ⅳ "iv") - (?\ⅴ "v") - (?\ⅵ "vi") - (?\ⅶ "vii") - (?\ⅷ "viii") - (?\ⅸ "ix") - (?\ⅹ "x") - (?\ⅺ "xi") - (?\ⅻ "xii") - (?\ⅼ "l") - (?\ⅽ "c") - (?\ⅾ "d") - (?\ⅿ "m") - (?\ↀ "1000RCD") - (?\ↁ "5000R") - (?\ↂ "10000R") - (?\← "<-") - (?\↑ "-^") - (?\→ "->") - (?\↓ "-v") - (?\↔ "<->") - (?\↕ "UD") - (?\↖ "") - (?\↘ "!!>") - (?\↙ "V") - (?\⇐ "<=") - (?\⇑ "^^") - (?\⇒ "=>") - (?\⇓ "vv") - (?\⇔ "<=>") - (?\∀ "FA") - (?\∂ "\\partial") - (?\∃ "TE") - (?\∅ "{}") - (?\∆ "Delta") - (?\∇ "Nabla") - (?\∈ "(-") - (?\∉ "!(-") - (?\∊ "(-") - (?\∋ "-)") - (?\∌ "!-)") - (?\∍ "-)") - (?\∎ " qed") - (?\∏ "\\prod") - (?\∑ "\\sum") - (?\− " -") - (?\∓ "-/+") - (?\∔ ".+") - (?\∕ "/") - (?\∖ " - ") - (?\∗ "*") - (?\∘ " ° ") - (?\∙ "sb") - (?\√ " SQRT ") - (?\∛ " ROOT³ ") - (?\∜ " ROOT4 ") - (?\∝ "0(") - (?\∞ "infty") - (?\∟ "-L") - (?\∠ "-V") - (?\∥ "PP") - (?\∦ " !PP ") - (?\∧ "AND") - (?\∨ "OR") - (?\∩ "(U") - (?\∪ ")U") - (?\∫ "\\int ") - (?\∬ "DI") - (?\∮ "Io") - (?\∴ ".:") - (?\∵ ":.") - (?\∶ ":R") - (?\∷ "::") - (?\∼ "?1") - (?\∾ "CG") - (?\≃ "?-") - (?\≅ "?=") - (?\≈ "~=") - (?\≉ " !~= ") - (?\≌ "=?") - (?\≓ "HI") - (?\≔ ":=") - (?\≕ "=:") - (?\≠ "!=") - (?\≡ "=3") - (?\≢ " !=3 ") - (?\≤ "=<") - (?\≥ ">=") - (?\≦ ".LE.") - (?\≧ ".GE.") - (?\≨ ".LT.NOT.EQ.") - (?\≩ ".GT.NOT.EQ.") - (?\≪ "<<") - (?\≫ ">>") - (?\≮ "!<") - (?\≯ "!>") - (?\≶ " <> ") - (?\≷ " >< ") - (?\⊂ "(C") - (?\⊃ ")C") - (?\⊄ " !(C ") - (?\⊅ " !)C ") - (?\⊆ "(_") - (?\⊇ ")_") - (?\⊕ "(+)") - (?\⊖ "(-)") - (?\⊗ "(×)") - (?\⊘ "(/)") - (?\⊙ "(·)") - (?\⊚ "(°)") - (?\⊛ "(*)") - (?\⊜ "(=)") - (?\⊝ "(-)") - (?\⊞ "[+]") - (?\⊟ "[-]") - (?\⊠ "[×]") - (?\⊡ "[·]") - (?\⊥ "-T") - (?\⊧ " MODELS ") - (?\⊨ " TRUE ") - (?\⊩ " FORCES ") - (?\⊬ " !PROVES ") - (?\⊭ " NOT TRUE ") - (?\⊮ " !FORCES ") - (?\⊲ " NORMAL SUBGROUP OF ") - (?\⊳ " CONTAINS AS NORMAL SUBGROUP ") - (?\⊴ " NORMAL SUBGROUP OF OR EQUAL TO ") - (?\⊵ " CONTAINS AS NORMAL SUBGROUP OR EQUAL TO ") - (?\⊸ " MULTIMAP ") - (?\⊺ " INTERCALATE ") - (?\⊻ " XOR ") - (?\⊼ " NAND ") - (?\⋅ " · ") - (?\⋖ "<.") - (?\⋗ ">.") - (?\⋘ "<<<") - (?\⋙ ">>>") - (?\⋮ ":3") - (?\⋯ ".3") - (?\⌂ "Eh") - (?\⌇ "~~") - (?\⌈ "<7") - (?\⌉ ">7") - (?\⌊ "7<") - (?\⌋ "7>") - (?\⌐ "NI") - (?\⌒ "(A") - (?\⌕ "TR") - (?\⌘ "88") - (?\⌠ "Iu") - (?\⌡ "Il") - (?\⌢ ":(") - (?\⌣ ":)") - (?\⌤ "|^|") - (?\⌧ "[X]") - (?\〈 "") - (?\␣ "Vs") - (?\⑀ "1h") - (?\⑁ "3h") - (?\⑂ "2h") - (?\⑃ "4h") - (?\⑆ "1j") - (?\⑇ "2j") - (?\⑈ "3j") - (?\⑉ "4j") - (?\① "1-o") - (?\② "2-o") - (?\③ "3-o") - (?\④ "4-o") - (?\⑤ "5-o") - (?\⑥ "6-o") - (?\⑦ "7-o") - (?\⑧ "8-o") - (?\⑨ "9-o") - (?\⑩ "10-o") - (?\⑪ "11-o") - (?\⑫ "12-o") - (?\⑬ "13-o") - (?\⑭ "14-o") - (?\⑮ "15-o") - (?\⑯ "16-o") - (?\⑰ "17-o") - (?\⑱ "18-o") - (?\⑲ "19-o") - (?\⑳ "20-o") - (?\⑴ "(1)") - (?\⑵ "(2)") - (?\⑶ "(3)") - (?\⑷ "(4)") - (?\⑸ "(5)") - (?\⑹ "(6)") - (?\⑺ "(7)") - (?\⑻ "(8)") - (?\⑼ "(9)") - (?\⑽ "(10)") - (?\⑾ "(11)") - (?\⑿ "(12)") - (?\⒀ "(13)") - (?\⒁ "(14)") - (?\⒂ "(15)") - (?\⒃ "(16)") - (?\⒄ "(17)") - (?\⒅ "(18)") - (?\⒆ "(19)") - (?\⒇ "(20)") - (?\⒈ "1.") - (?\⒉ "2.") - (?\⒊ "3.") - (?\⒋ "4.") - (?\⒌ "5.") - (?\⒍ "6.") - (?\⒎ "7.") - (?\⒏ "8.") - (?\⒐ "9.") - (?\⒑ "10.") - (?\⒒ "11.") - (?\⒓ "12.") - (?\⒔ "13.") - (?\⒕ "14.") - (?\⒖ "15.") - (?\⒗ "16.") - (?\⒘ "17.") - (?\⒙ "18.") - (?\⒚ "19.") - (?\⒛ "20.") - (?\⒜ "(a)") - (?\⒝ "(b)") - (?\⒞ "(c)") - (?\⒟ "(d)") - (?\⒠ "(e)") - (?\⒡ "(f)") - (?\⒢ "(g)") - (?\⒣ "(h)") - (?\⒤ "(i)") - (?\⒥ "(j)") - (?\⒦ "(k)") - (?\⒧ "(l)") - (?\⒨ "(m)") - (?\⒩ "(n)") - (?\⒪ "(o)") - (?\⒫ "(p)") - (?\⒬ "(q)") - (?\⒭ "(r)") - (?\⒮ "(s)") - (?\⒯ "(t)") - (?\⒰ "(u)") - (?\⒱ "(v)") - (?\⒲ "(w)") - (?\⒳ "(x)") - (?\⒴ "(y)") - (?\⒵ "(z)") - (?\Ⓐ "A-o") - (?\Ⓑ "B-o") - (?\Ⓒ "C-o") - (?\Ⓓ "D-o") - (?\Ⓔ "E-o") - (?\Ⓕ "F-o") - (?\Ⓖ "G-o") - (?\Ⓗ "H-o") - (?\Ⓘ "I-o") - (?\Ⓙ "J-o") - (?\Ⓚ "K-o") - (?\Ⓛ "L-o") - (?\Ⓜ "M-o") - (?\Ⓝ "N-o") - (?\Ⓞ "O-o") - (?\Ⓟ "P-o") - (?\Ⓠ "Q-o") - (?\Ⓡ "R-o") - (?\Ⓢ "S-o") - (?\Ⓣ "T-o") - (?\Ⓤ "U-o") - (?\Ⓥ "V-o") - (?\Ⓦ "W-o") - (?\Ⓧ "X-o") - (?\Ⓨ "Y-o") - (?\Ⓩ "Z-o") - (?\ⓐ "a-o") - (?\ⓑ "b-o") - (?\ⓒ "c-o") - (?\ⓓ "d-o") - (?\ⓔ "e-o") - (?\ⓕ "f-o") - (?\ⓖ "g-o") - (?\ⓗ "h-o") - (?\ⓘ "i-o") - (?\ⓙ "j-o") - (?\ⓚ "k-o") - (?\ⓛ "l-o") - (?\ⓜ "m-o") - (?\ⓝ "n-o") - (?\ⓞ "o-o") - (?\ⓟ "p-o") - (?\ⓠ "q-o") - (?\ⓡ "r-o") - (?\ⓢ "s-o") - (?\ⓣ "t-o") - (?\ⓤ "u-o") - (?\ⓥ "v-o") - (?\ⓦ "w-o") - (?\ⓧ "x-o") - (?\ⓨ "y-o") - (?\ⓩ "z-o") - (?\⓪ "0-o") - (?\─ "-") - (?\━ "=") - (?\│ "|") - (?\┃ "|") - (?\┄ "-") - (?\┅ "=") - (?\┆ "|") - (?\┇ "|") - (?\┈ "-") - (?\┉ "=") - (?\┊ "|") - (?\┋ "|") - (?\┌ "+") - (?\┍ "+") - (?\┎ "+") - (?\┏ "+") - (?\┐ "+") - (?\┑ "+") - (?\┒ "+") - (?\┓ "+") - (?\└ "+") - (?\┕ "+") - (?\┖ "+") - (?\┗ "+") - (?\┘ "+") - (?\┙ "+") - (?\┚ "+") - (?\┛ "+") - (?\├ "+") - (?\┝ "+") - (?\┞ "+") - (?\┟ "+") - (?\┠ "+") - (?\┡ "+") - (?\┢ "+") - (?\┣ "+") - (?\┤ "+") - (?\┥ "+") - (?\┦ "+") - (?\┧ "+") - (?\┨ "+") - (?\┩ "+") - (?\┪ "+") - (?\┫ "+") - (?\┬ "+") - (?\┭ "+") - (?\┮ "+") - (?\┯ "+") - (?\┰ "+") - (?\┱ "+") - (?\┲ "+") - (?\┳ "+") - (?\┴ "+") - (?\┵ "+") - (?\┶ "+") - (?\┷ "+") - (?\┸ "+") - (?\┹ "+") - (?\┺ "+") - (?\┻ "+") - (?\┼ "+") - (?\┽ "+") - (?\┾ "+") - (?\┿ "+") - (?\╀ "+") - (?\╁ "+") - (?\╂ "+") - (?\╃ "+") - (?\╄ "+") - (?\╅ "+") - (?\╆ "+") - (?\╇ "+") - (?\╈ "+") - (?\╉ "+") - (?\╊ "+") - (?\╋ "+") - (?\╌ "+") - (?\╍ "+") - (?\╎ "+") - (?\╏ "+") - (?\═ "+") - (?\║ "+") - (?\╒ "+") - (?\╓ "+") - (?\╔ "+") - (?\╕ "+") - (?\╖ "+") - (?\╗ "+") - (?\╘ "+") - (?\╙ "+") - (?\╚ "+") - (?\╛ "+") - (?\╜ "+") - (?\╝ "+") - (?\╞ "+") - (?\╟ "+") - (?\╠ "+") - (?\╡ "+") - (?\╢ "+") - (?\╣ "+") - (?\╤ "+") - (?\╥ "+") - (?\╦ "+") - (?\╧ "+") - (?\╨ "+") - (?\╩ "+") - (?\╪ "+") - (?\╫ "+") - (?\╬ "+") - (?\╱ "/") - (?\╲ "\\") - (?\▀ "TB") - (?\▄ "LB") - (?\█ "FB") - (?\▌ "lB") - (?\▐ "RB") - (?\░ ".S") - (?\▒ ":S") - (?\▓ "?S") - (?\■ "fS") - (?\□ "OS") - (?\▢ "RO") - (?\▣ "Rr") - (?\▤ "RF") - (?\▥ "RY") - (?\▦ "RH") - (?\▧ "RZ") - (?\▨ "RK") - (?\▩ "RX") - (?\▪ "sB") - (?\▬ "SR") - (?\▭ "Or") - (?\▲ "^") - (?\△ "uT") - (?\▶ "|>") - (?\▷ "Tr") - (?\► "|>") - (?\▼ "v") - (?\▽ "dT") - (?\◀ "<|") - (?\◁ "Tl") - (?\◄ "<|") - (?\◆ "Db") - (?\◇ "Dw") - (?\◊ "LZ") - (?\○ "0m") - (?\◎ "0o") - (?\● "0M") - (?\◐ "0L") - (?\◑ "0R") - (?\◘ "Sn") - (?\◙ "Ic") - (?\◢ "Fd") - (?\◣ "Bd") - (?\◯ "Ci") - (?\★ "*2") - (?\☆ "*1") - (?\☎ "TEL") - (?\☏ "tel") - (?\☜ "<--") - (?\☞ "-->") - (?\☡ "CAUTION ") - (?\☧ "XP") - (?\☹ ":-(") - (?\☺ ":-)") - (?\☻ "(-:") - (?\☼ "SU") - (?\♀ "f.") - (?\♂ "m.") - (?\♠ "cS") - (?\♡ "cH") - (?\♢ "cD") - (?\♣ "cC") - (?\♤ "cS-") - (?\♥ "cH-") - (?\♦ "cD-") - (?\♧ "cC-") - (?\♩ "Md") - (?\♪ "M8") - (?\♫ "M2") - (?\♬ "M16") - (?\♭ "b") - (?\♮ "Mx") - (?\♯ "#") - (?\✓ "X") - (?\✗ "X") - (?\✠ "-X") - (?\  " ") - (?\、 ",_") - (?\。 "._") - (?\〃 "+\"") - (?\〄 "JIS") - (?\々 "*_") - (?\〆 ";_") - (?\〇 "0_") - (?\《 "<+") - (?\》 ">+") - (?\「 "<'") - (?\」 ">'") - (?\『 "<\"") - (?\』 ">\"") - (?\【 "(\"") - (?\】 ")\"") - (?\〒 "=T") - (?\〓 "=_") - (?\〔 "('") - (?\〕 ")'") - (?\〖 "(I") - (?\〗 ")I") - (?\〚 "[[") - (?\〛 "]]") - (?\〜 "-?") - (?\〠 "=T:)") - (?\〿 " ") - (?\ぁ "A5") - (?\あ "a5") - (?\ぃ "I5") - (?\い "i5") - (?\ぅ "U5") - (?\う "u5") - (?\ぇ "E5") - (?\え "e5") - (?\ぉ "O5") - (?\お "o5") - (?\か "ka") - (?\が "ga") - (?\き "ki") - (?\ぎ "gi") - (?\く "ku") - (?\ぐ "gu") - (?\け "ke") - (?\げ "ge") - (?\こ "ko") - (?\ご "go") - (?\さ "sa") - (?\ざ "za") - (?\し "si") - (?\じ "zi") - (?\す "su") - (?\ず "zu") - (?\せ "se") - (?\ぜ "ze") - (?\そ "so") - (?\ぞ "zo") - (?\た "ta") - (?\だ "da") - (?\ち "ti") - (?\ぢ "di") - (?\っ "tU") - (?\つ "tu") - (?\づ "du") - (?\て "te") - (?\で "de") - (?\と "to") - (?\ど "do") - (?\な "na") - (?\に "ni") - (?\ぬ "nu") - (?\ね "ne") - (?\の "no") - (?\は "ha") - (?\ば "ba") - (?\ぱ "pa") - (?\ひ "hi") - (?\び "bi") - (?\ぴ "pi") - (?\ふ "hu") - (?\ぶ "bu") - (?\ぷ "pu") - (?\へ "he") - (?\べ "be") - (?\ぺ "pe") - (?\ほ "ho") - (?\ぼ "bo") - (?\ぽ "po") - (?\ま "ma") - (?\み "mi") - (?\む "mu") - (?\め "me") - (?\も "mo") - (?\ゃ "yA") - (?\や "ya") - (?\ゅ "yU") - (?\ゆ "yu") - (?\ょ "yO") - (?\よ "yo") - (?\ら "ra") - (?\り "ri") - (?\る "ru") - (?\れ "re") - (?\ろ "ro") - (?\ゎ "wA") - (?\わ "wa") - (?\ゐ "wi") - (?\ゑ "we") - (?\を "wo") - (?\ん "n5") - (?\ゔ "vu") - (?\゛ "\"5") - (?\゜ "05") - (?\ゝ "*5") - (?\ゞ "+5") - (?\ァ "a6") - (?\ア "A6") - (?\ィ "i6") - (?\イ "I6") - (?\ゥ "u6") - (?\ウ "U6") - (?\ェ "e6") - (?\エ "E6") - (?\ォ "o6") - (?\オ "O6") - (?\カ "Ka") - (?\ガ "Ga") - (?\キ "Ki") - (?\ギ "Gi") - (?\ク "Ku") - (?\グ "Gu") - (?\ケ "Ke") - (?\ゲ "Ge") - (?\コ "Ko") - (?\ゴ "Go") - (?\サ "Sa") - (?\ザ "Za") - (?\シ "Si") - (?\ジ "Zi") - (?\ス "Su") - (?\ズ "Zu") - (?\セ "Se") - (?\ゼ "Ze") - (?\ソ "So") - (?\ゾ "Zo") - (?\タ "Ta") - (?\ダ "Da") - (?\チ "Ti") - (?\ヂ "Di") - (?\ッ "TU") - (?\ツ "Tu") - (?\ヅ "Du") - (?\テ "Te") - (?\デ "De") - (?\ト "To") - (?\ド "Do") - (?\ナ "Na") - (?\ニ "Ni") - (?\ヌ "Nu") - (?\ネ "Ne") - (?\ノ "No") - (?\ハ "Ha") - (?\バ "Ba") - (?\パ "Pa") - (?\ヒ "Hi") - (?\ビ "Bi") - (?\ピ "Pi") - (?\フ "Hu") - (?\ブ "Bu") - (?\プ "Pu") - (?\ヘ "He") - (?\ベ "Be") - (?\ペ "Pe") - (?\ホ "Ho") - (?\ボ "Bo") - (?\ポ "Po") - (?\マ "Ma") - (?\ミ "Mi") - (?\ム "Mu") - (?\メ "Me") - (?\モ "Mo") - (?\ャ "YA") - (?\ヤ "Ya") - (?\ュ "YU") - (?\ユ "Yu") - (?\ョ "YO") - (?\ヨ "Yo") - (?\ラ "Ra") - (?\リ "Ri") - (?\ル "Ru") - (?\レ "Re") - (?\ロ "Ro") - (?\ヮ "WA") - (?\ワ "Wa") - (?\ヰ "Wi") - (?\ヱ "We") - (?\ヲ "Wo") - (?\ン "N6") - (?\ヴ "Vu") - (?\ヵ "KA") - (?\ヶ "KE") - (?\ヷ "Va") - (?\ヸ "Vi") - (?\ヹ "Ve") - (?\ヺ "Vo") - (?\・ ".6") - (?\ー "-6") - (?\ヽ "*6") - (?\ヾ "+6") - (?\ㄅ "b4") - (?\ㄆ "p4") - (?\ㄇ "m4") - (?\ㄈ "f4") - (?\ㄉ "d4") - (?\ㄊ "t4") - (?\ㄋ "n4") - (?\ㄌ "l4") - (?\ㄍ "g4") - (?\ㄎ "k4") - (?\ㄏ "h4") - (?\ㄐ "j4") - (?\ㄑ "q4") - (?\ㄒ "x4") - (?\ㄓ "zh") - (?\ㄔ "ch") - (?\ㄕ "sh") - (?\ㄖ "r4") - (?\ㄗ "z4") - (?\ㄘ "c4") - (?\ㄙ "s4") - (?\ㄚ "a4") - (?\ㄛ "o4") - (?\ㄜ "e4") - (?\ㄝ "eh4") - (?\ㄞ "ai") - (?\ㄟ "ei") - (?\ㄠ "au") - (?\ㄡ "ou") - (?\ㄢ "an") - (?\ㄣ "en") - (?\ㄤ "aN") - (?\ㄥ "eN") - (?\ㄦ "er") - (?\ㄧ "i4") - (?\ㄨ "u4") - (?\ㄩ "iu") - (?\ㄪ "v4") - (?\ㄫ "nG") - (?\ㄬ "gn") - (?\㈜ "(JU)") - (?\㈠ "1c") - (?\㈡ "2c") - (?\㈢ "3c") - (?\㈣ "4c") - (?\㈤ "5c") - (?\㈥ "6c") - (?\㈦ "7c") - (?\㈧ "8c") - (?\㈨ "9c") - (?\㈩ "10c") - (?\㉿ "KSC") - (?\㏂ "am") - (?\㏘ "pm") - (?\ff "ff") - (?\fi "fi") - (?\fl "fl") - (?\ffi "ffi") - (?\ffl "ffl") - (?\ſt "St") - (?\st "st") - (?\ﹽ "3+;") - (?\ﺂ "aM.") - (?\ﺄ "aH.") - (?\ﺈ "ah.") - (?\ﺍ "a+-") - (?\ﺎ "a+.") - (?\ﺏ "b+-") - (?\ﺐ "b+.") - (?\ﺑ "b+,") - (?\ﺒ "b+;") - (?\ﺓ "tm-") - (?\ﺔ "tm.") - (?\ﺕ "t+-") - (?\ﺖ "t+.") - (?\ﺗ "t+,") - (?\ﺘ "t+;") - (?\ﺙ "tk-") - (?\ﺚ "tk.") - (?\ﺛ "tk,") - (?\ﺜ "tk;") - (?\ﺝ "g+-") - (?\ﺞ "g+.") - (?\ﺟ "g+,") - (?\ﺠ "g+;") - (?\ﺡ "hk-") - (?\ﺢ "hk.") - (?\ﺣ "hk,") - (?\ﺤ "hk;") - (?\ﺥ "x+-") - (?\ﺦ "x+.") - (?\ﺧ "x+,") - (?\ﺨ "x+;") - (?\ﺩ "d+-") - (?\ﺪ "d+.") - (?\ﺫ "dk-") - (?\ﺬ "dk.") - (?\ﺭ "r+-") - (?\ﺮ "r+.") - (?\ﺯ "z+-") - (?\ﺰ "z+.") - (?\ﺱ "s+-") - (?\ﺲ "s+.") - (?\ﺳ "s+,") - (?\ﺴ "s+;") - (?\ﺵ "sn-") - (?\ﺶ "sn.") - (?\ﺷ "sn,") - (?\ﺸ "sn;") - (?\ﺹ "c+-") - (?\ﺺ "c+.") - (?\ﺻ "c+,") - (?\ﺼ "c+;") - (?\ﺽ "dd-") - (?\ﺾ "dd.") - (?\ﺿ "dd,") - (?\ﻀ "dd;") - (?\ﻁ "tj-") - (?\ﻂ "tj.") - (?\ﻃ "tj,") - (?\ﻄ "tj;") - (?\ﻅ "zH-") - (?\ﻆ "zH.") - (?\ﻇ "zH,") - (?\ﻈ "zH;") - (?\ﻉ "e+-") - (?\ﻊ "e+.") - (?\ﻋ "e+,") - (?\ﻌ "e+;") - (?\ﻍ "i+-") - (?\ﻎ "i+.") - (?\ﻏ "i+,") - (?\ﻐ "i+;") - (?\ﻑ "f+-") - (?\ﻒ "f+.") - (?\ﻓ "f+,") - (?\ﻔ "f+;") - (?\ﻕ "q+-") - (?\ﻖ "q+.") - (?\ﻗ "q+,") - (?\ﻘ "q+;") - (?\ﻙ "k+-") - (?\ﻚ "k+.") - (?\ﻛ "k+,") - (?\ﻜ "k+;") - (?\ﻝ "l+-") - (?\ﻞ "l+.") - (?\ﻟ "l+,") - (?\ﻠ "l+;") - (?\ﻡ "m+-") - (?\ﻢ "m+.") - (?\ﻣ "m+,") - (?\ﻤ "m+;") - (?\ﻥ "n+-") - (?\ﻦ "n+.") - (?\ﻧ "n+,") - (?\ﻨ "n+;") - (?\ﻩ "h+-") - (?\ﻪ "h+.") - (?\ﻫ "h+,") - (?\ﻬ "h+;") - (?\ﻭ "w+-") - (?\ﻮ "w+.") - (?\ﻯ "j+-") - (?\ﻰ "j+.") - (?\ﻱ "y+-") - (?\ﻲ "y+.") - (?\ﻳ "y+,") - (?\ﻴ "y+;") - (?\ﻵ "lM-") - (?\ﻶ "lM.") - (?\ﻷ "lH-") - (?\ﻸ "lH.") - (?\ﻹ "lh-") - (?\ﻺ "lh.") - (?\ﻻ "la-") - (?\ﻼ "la.") - (?\! "!") - (?\" "\"") - (?\# "#") - (?\$ "$") - (?\% "%") - (?\& "&") - (?\' "'") - (?\( "(") - (?\) ")") - (?\* "*") - (?\+ "+") - (?\, ",") - (?\- "-") - (?\. ".") - (?\/ "/") - (?\0 "0") - (?\1 "1") - (?\2 "2") - (?\3 "3") - (?\4 "4") - (?\5 "5") - (?\6 "6") - (?\7 "7") - (?\8 "8") - (?\9 "9") - (?\: ":") - (?\; ";") - (?\< "<") - (?\= "=") - (?\> ">") - (?\? "?") - (?\@ "@") - (?\A "A") - (?\B "B") - (?\C "C") - (?\D "D") - (?\E "E") - (?\F "F") - (?\G "G") - (?\H "H") - (?\I "I") - (?\J "J") - (?\K "K") - (?\L "L") - (?\M "M") - (?\N "N") - (?\O "O") - (?\P "P") - (?\Q "Q") - (?\R "R") - (?\S "S") - (?\T "T") - (?\U "U") - (?\V "V") - (?\W "W") - (?\X "X") - (?\Y "Y") - (?\Z "Z") - (?\[ "[") - (?\\ "\\") - (?\] "]") - (?\^ "^") - (?\_ "_") - (?\` "`") - (?\a "a") - (?\b "b") - (?\c "c") - (?\d "d") - (?\e "e") - (?\f "f") - (?\g "g") - (?\h "h") - (?\i "i") - (?\j "j") - (?\k "k") - (?\l "l") - (?\m "m") - (?\n "n") - (?\o "o") - (?\p "p") - (?\q "q") - (?\r "r") - (?\s "s") - (?\t "t") - (?\u "u") - (?\v "v") - (?\w "w") - (?\x "x") - (?\y "y") - (?\z "z") - (?\{ "{") - (?\| "|") - (?\} "}") - (?\~ "~") - (?\。 ".") - (?\「 "\"") - (?\」 "\"") - (?\、 ",") - ;; Not from Lynx - (? "") - (?� "?"))))) + (let ((latin1-display-format "%s")) + (mapc + (lambda (l) + (or (char-displayable-p (car l)) + (apply 'latin1-display-char l))) + ;; Table derived by running Lynx on a suitable list of + ;; characters in a utf-8 file, except for some added by + ;; hand at the end. + '((?\Ā "A") + (?\ā "a") + (?\Ă "A") + (?\ă "a") + (?\Ą "A") + (?\ą "a") + (?\Ć "C") + (?\ć "c") + (?\Ĉ "C") + (?\ĉ "c") + (?\Ċ "C") + (?\ċ "c") + (?\Č "C") + (?\č "c") + (?\Ď "D") + (?\ď "d") + (?\Đ "Ð") + (?\đ "d/") + (?\Ē "E") + (?\ē "e") + (?\Ĕ "E") + (?\ĕ "e") + (?\Ė "E") + (?\ė "e") + (?\Ę "E") + (?\ę "e") + (?\Ě "E") + (?\ě "e") + (?\Ĝ "G") + (?\ĝ "g") + (?\Ğ "G") + (?\ğ "g") + (?\Ġ "G") + (?\ġ "g") + (?\Ģ "G") + (?\ģ "g") + (?\Ĥ "H") + (?\ĥ "h") + (?\Ħ "H/") + (?\ħ "H") + (?\Ĩ "I") + (?\ĩ "i") + (?\Ī "I") + (?\ī "i") + (?\Ĭ "I") + (?\ĭ "i") + (?\Į "I") + (?\į "i") + (?\İ "I") + (?\ı "i") + (?\IJ "IJ") + (?\ij "ij") + (?\Ĵ "J") + (?\ĵ "j") + (?\Ķ "K") + (?\ķ "k") + (?\ĸ "kk") + (?\Ĺ "L") + (?\ĺ "l") + (?\Ļ "L") + (?\ļ "l") + (?\Ľ "L") + (?\ľ "l") + (?\Ŀ "L.") + (?\ŀ "l.") + (?\Ł "L/") + (?\ł "l/") + (?\Ń "N") + (?\ń "n") + (?\Ņ "N") + (?\ņ "n") + (?\Ň "N") + (?\ň "n") + (?\ʼn "'n") + (?\Ŋ "NG") + (?\ŋ "N") + (?\Ō "O") + (?\ō "o") + (?\Ŏ "O") + (?\ŏ "o") + (?\Ő "O\"") + (?\ő "o\"") + (?\Œ "OE") + (?\œ "oe") + (?\Ŕ "R") + (?\ŕ "r") + (?\Ŗ "R") + (?\ŗ "r") + (?\Ř "R") + (?\ř "r") + (?\Ś "S") + (?\ś "s") + (?\Ŝ "S") + (?\ŝ "s") + (?\Ş "S") + (?\ş "s") + (?\Š "S") + (?\š "s") + (?\Ţ "T") + (?\ţ "t") + (?\Ť "T") + (?\ť "t") + (?\Ŧ "T/") + (?\ŧ "t/") + (?\Ũ "U") + (?\ũ "u") + (?\Ū "U") + (?\ū "u") + (?\Ŭ "U") + (?\ŭ "u") + (?\Ů "U") + (?\ů "u") + (?\Ű "U\"") + (?\ű "u\"") + (?\Ų "U") + (?\ų "u") + (?\Ŵ "W") + (?\ŵ "w") + (?\Ŷ "Y") + (?\ŷ "y") + (?\Ÿ "Y") + (?\Ź "Z") + (?\ź "z") + (?\Ż "Z") + (?\ż "z") + (?\Ž "Z") + (?\ž "z") + (?\ſ "s1") + (?\Ƈ "C2") + (?\ƈ "c2") + (?\Ƒ "F2") + (?\ƒ " f") + (?\Ƙ "K2") + (?\ƙ "k2") + (?\Ơ "O9") + (?\ơ "o9") + (?\Ƣ "OI") + (?\ƣ "oi") + (?\Ʀ "yr") + (?\Ư "U9") + (?\ư "u9") + (?\Ƶ "Z/") + (?\ƶ "z/") + (?\Ʒ "ED") + (?\Ǎ "A") + (?\ǎ "a") + (?\Ǐ "I") + (?\ǐ "i") + (?\Ǒ "O") + (?\ǒ "o") + (?\Ǔ "U") + (?\ǔ "u") + (?\Ǖ "U:-") + (?\ǖ "u:-") + (?\Ǘ "U:'") + (?\ǘ "u:'") + (?\Ǚ "U:<") + (?\ǚ "u:<") + (?\Ǜ "U:!") + (?\ǜ "u:!") + (?\Ǟ "A1") + (?\ǟ "a1") + (?\Ǡ "A7") + (?\ǡ "a7") + (?\Ǣ "A3") + (?\ǣ "a3") + (?\Ǥ "G/") + (?\ǥ "g/") + (?\Ǧ "G") + (?\ǧ "g") + (?\Ǩ "K") + (?\ǩ "k") + (?\Ǫ "O") + (?\ǫ "o") + (?\Ǭ "O1") + (?\ǭ "o1") + (?\Ǯ "EZ") + (?\ǯ "ez") + (?\ǰ "j") + (?\Ǵ "G") + (?\ǵ "g") + (?\Ǻ "AA'") + (?\ǻ "aa'") + (?\Ǽ "AE'") + (?\ǽ "ae'") + (?\Ǿ "O/'") + (?\ǿ "o/'") + (?\Ȁ "A!!") + (?\ȁ "a!!") + (?\Ȃ "A)") + (?\ȃ "a)") + (?\Ȅ "E!!") + (?\ȅ "e!!") + (?\Ȇ "E)") + (?\ȇ "e)") + (?\Ȉ "I!!") + (?\ȉ "i!!") + (?\Ȋ "I)") + (?\ȋ "i)") + (?\Ȍ "O!!") + (?\ȍ "o!!") + (?\Ȏ "O)") + (?\ȏ "o)") + (?\Ȑ "R!!") + (?\ȑ "r!!") + (?\Ȓ "R)") + (?\ȓ "r)") + (?\Ȕ "U!!") + (?\ȕ "u!!") + (?\Ȗ "U)") + (?\ȗ "u)") + (?\ȝ "Z") + (?\ɑ "A") + (?\ɒ "A.") + (?\ɓ "b`") + (?\ɔ "O") + (?\ɖ "d.") + (?\ɗ "d`") + (?\ɘ "@") + (?\ə "@") + (?\ɚ "R") + (?\ɛ "E") + (?\ɜ "V\"") + (?\ɝ "R") + (?\ɞ "O\"") + (?\ɟ "J") + (?\ɠ "g`") + (?\ɡ "g") + (?\ɢ "G") + (?\ɣ "Q") + (?\ɤ "o-") + (?\ɥ "j") + (?\ɦ "h") + (?\ɨ "i\"") + (?\ɩ "I") + (?\ɪ "I") + (?\ɫ "L") + (?\ɬ "L") + (?\ɭ "l.") + (?\ɮ "z") + (?\ɯ "u-") + (?\ɰ "j") + (?\ɱ "M") + (?\ɳ "n.") + (?\ɴ "n\"") + (?\ɵ "@.") + (?\ɶ "&.") + (?\ɷ "U") + (?\ɹ "r") + (?\ɺ "*") + (?\ɻ "r.") + (?\ɽ "*.") + (?\ɾ "*") + (?\ʀ "R") + (?\ʁ "g\"") + (?\ʂ "s.") + (?\ʃ "S") + (?\ʄ "J`") + (?\ʇ "t!") + (?\ʈ "t.") + (?\ʉ "u\"") + (?\ʊ "U") + (?\ʋ "r") + (?\ʌ "V") + (?\ʍ "w") + (?\ʎ "l^") + (?\ʏ "I.") + (?\ʐ "z.") + (?\ʒ "Z") + (?\ʔ "?") + (?\ʕ "H") + (?\ʖ "l!") + (?\ʗ "c!") + (?\ʘ "p!") + (?\ʙ "b") + (?\ʛ "G`") + (?\ʝ "j") + (?\ʞ "k!") + (?\ʟ "L") + (?\ʠ "q`") + (?\ʤ "d3") + (?\ʦ "ts") + (?\ʧ "tS") + (?\ʰ "") + (?\ʱ "") + (?\ʲ ";") + (?\ʳ "") + (?\ʷ "") + (?\ʻ ";S") + (?\ʼ "`") + (?\ˆ "^") + (?\ˇ "'<") + (?\ˈ "|") + (?\ˉ "1-") + (?\ˋ "1!") + (?\ː ":") + (?\ˑ ":\\") + (?\˖ "+") + (?\˗ "-") + (?\˘ "'(") + (?\˙ "'.") + (?\˚ "'0") + (?\˛ "';") + (?\˜ "~") + (?\˝ "'\"") + (?\˥ "_T") + (?\˦ "_H") + (?\˧ "_M") + (?\˨ "_L") + (?\˩ "_B") + (?\ˬ "_v") + (?\ˮ "''") + (?\̀ "`") + (?\́ "'") + (?\̂ "^") + (?\̃ "~") + (?\̄ "¯") + (?\̇ "·") + (?\̈ "¨") + (?\̊ "°") + (?\̋ "''") + (?\̍ "|") + (?\̎ "||") + (?\̏ "``") + (?\̡ ";") + (?\̢ ".") + (?\̣ ".") + (?\̤ "") + (?\̥ "") + (?\̦ ",") + (?\̧ "¸") + (?\̩ "-") + (?\̪ "[") + (?\̫ "") + (?\̴ "~") + (?\̷ "/") + (?\̸ "/") + (?\̀ "`") + (?\́ "'") + (?\͂ "~") + (?\̈́ "'%") + (?\ͅ "j3") + (?\͇ "=") + (?\͠ "~~") + (?\ʹ "'") + (?\͵ ",") + (?\ͺ "j3") + (?\; "?%") + (?\΄ "'*") + (?\΅ "'%") + (?\Ά "A'") + (?\· "·") + (?\Έ "E'") + (?\Ή "Y%") + (?\Ί "I'") + (?\Ό "O'") + (?\Ύ "U%") + (?\Ώ "W%") + (?\ΐ "i3") + (?\Α "A") + (?\Β "B") + (?\Γ "G") + (?\Δ "D") + (?\Ε "E") + (?\Ζ "Z") + (?\Η "Y") + (?\Θ "TH") + (?\Ι "I") + (?\Κ "K") + (?\Λ "L") + (?\Μ "M") + (?\Ν "N") + (?\Ξ "C") + (?\Ο "O") + (?\Π "P") + (?\Ρ "R") + (?\Σ "S") + (?\Τ "T") + (?\Υ "U") + (?\Φ "F") + (?\Χ "X") + (?\Ψ "Q") + (?\Ω "W*") + (?\Ϊ "J") + (?\Ϋ "V*") + (?\ά "a'") + (?\έ "e'") + (?\ή "y%") + (?\ί "i'") + (?\ΰ "u3") + (?\α "a") + (?\β "b") + (?\γ "g") + (?\δ "d") + (?\ε "e") + (?\ζ "z") + (?\η "y") + (?\θ "th") + (?\ι "i") + (?\κ "k") + (?\λ "l") + (?\μ "µ") + (?\ν "n") + (?\ξ "c") + (?\ο "o") + (?\π "p") + (?\ρ "r") + (?\ς "*s") + (?\σ "s") + (?\τ "t") + (?\υ "u") + (?\φ "f") + (?\χ "x") + (?\ψ "q") + (?\ω "w") + (?\ϊ "j") + (?\ϋ "v*") + (?\ό "o'") + (?\ύ "u%") + (?\ώ "w%") + (?\ϐ "beta ") + (?\ϑ "theta ") + (?\ϒ "upsi ") + (?\ϕ "phi ") + (?\ϖ "pi ") + (?\ϗ "k.") + (?\Ϛ "T3") + (?\ϛ "t3") + (?\Ϝ "M3") + (?\ϝ "m3") + (?\Ϟ "K3") + (?\ϟ "k3") + (?\Ϡ "P3") + (?\ϡ "p3") + (?\ϰ "kappa ") + (?\ϱ "rho ") + (?\ϳ "J") + (?\ϴ "'%") + (?\ϵ "j3") + (?\Ё "IO") + (?\Ђ "D%") + (?\Ѓ "G%") + (?\Є "IE") + (?\Ѕ "DS") + (?\І "II") + (?\Ї "YI") + (?\Ј "J%") + (?\Љ "LJ") + (?\Њ "NJ") + (?\Ћ "Ts") + (?\Ќ "KJ") + (?\Ў "V%") + (?\Џ "DZ") + (?\А "A") + (?\Б "B") + (?\В "V") + (?\Г "G") + (?\Д "D") + (?\Е "E") + (?\Ж "ZH") + (?\З "Z") + (?\И "I") + (?\Й "J") + (?\К "K") + (?\Л "L") + (?\М "M") + (?\Н "N") + (?\О "O") + (?\П "P") + (?\Р "R") + (?\С "S") + (?\Т "T") + (?\У "U") + (?\Ф "F") + (?\Х "H") + (?\Ц "C") + (?\Ч "CH") + (?\Ш "SH") + (?\Щ "SCH") + (?\Ъ "\"") + (?\Ы "Y") + (?\Ь "'") + (?\Э "`E") + (?\Ю "YU") + (?\Я "YA") + (?\а "a") + (?\б "b") + (?\в "v") + (?\г "g") + (?\д "d") + (?\е "e") + (?\ж "zh") + (?\з "z") + (?\и "i") + (?\й "j") + (?\к "k") + (?\л "l") + (?\м "m") + (?\н "n") + (?\о "o") + (?\п "p") + (?\р "r") + (?\с "s") + (?\т "t") + (?\у "u") + (?\ф "f") + (?\х "h") + (?\ц "c") + (?\ч "ch") + (?\ш "sh") + (?\щ "sch") + (?\ъ "\"") + (?\ы "y") + (?\ь "'") + (?\э "`e") + (?\ю "yu") + (?\я "ya") + (?\ё "io") + (?\ђ "d%") + (?\ѓ "g%") + (?\є "ie") + (?\ѕ "ds") + (?\і "ii") + (?\ї "yi") + (?\ј "j%") + (?\љ "lj") + (?\њ "nj") + (?\ћ "ts") + (?\ќ "kj") + (?\ў "v%") + (?\џ "dz") + (?\Ѣ "Y3") + (?\ѣ "y3") + (?\Ѫ "O3") + (?\ѫ "o3") + (?\Ѳ "F3") + (?\ѳ "f3") + (?\Ѵ "V3") + (?\ѵ "v3") + (?\Ҁ "C3") + (?\ҁ "c3") + (?\Ґ "G3") + (?\ґ "g3") + (?\Ӕ "AE") + (?\ӕ "ae") + (?\ִ "i") + (?\ַ "a") + (?\ָ "o") + (?\ּ "u") + (?\ֿ "h") + (?\ׂ ":") + (?\א "#") + (?\ב "B+") + (?\ג "G+") + (?\ד "D+") + (?\ה "H+") + (?\ו "W+") + (?\ז "Z+") + (?\ח "X+") + (?\ט "Tj") + (?\י "J+") + (?\ך "K%") + (?\כ "K+") + (?\ל "L+") + (?\ם "M%") + (?\מ "M+") + (?\ן "N%") + (?\נ "N+") + (?\ס "S+") + (?\ע "E+") + (?\ף "P%") + (?\פ "P+") + (?\ץ "Zj") + (?\צ "ZJ") + (?\ק "Q+") + (?\ר "R+") + (?\ש "Sh") + (?\ת "T+") + (?\װ "v") + (?\ױ "oy") + (?\ײ "ey") + (?\، ",+") + (?\؛ ";+") + (?\؟ "?+") + (?\ء "H'") + (?\آ "aM") + (?\أ "aH") + (?\ؤ "wH") + (?\إ "ah") + (?\ئ "yH") + (?\ا "a+") + (?\ب "b+") + (?\ة "tm") + (?\ت "t+") + (?\ث "tk") + (?\ج "g+") + (?\ح "hk") + (?\خ "x+") + (?\د "d+") + (?\ذ "dk") + (?\ر "r+") + (?\ز "z+") + (?\س "s+") + (?\ش "sn") + (?\ص "c+") + (?\ض "dd") + (?\ط "tj") + (?\ظ "zH") + (?\ع "e+") + (?\غ "i+") + (?\ـ "++") + (?\ف "f+") + (?\ق "q+") + (?\ك "k+") + (?\ل "l+") + (?\م "m+") + (?\ن "n+") + (?\ه "h+") + (?\و "w+") + (?\ى "j+") + (?\ي "y+") + (?\ً ":+") + (?\ٌ "\"+") + (?\ٍ "=+") + (?\َ "/+") + (?\ُ "'+") + (?\ِ "1+") + (?\ّ "3+") + (?\ْ "0+") + (?\٠ "0a") + (?\١ "1a") + (?\٢ "2a") + (?\٣ "3a") + (?\٤ "4a") + (?\٥ "5a") + (?\٦ "6a") + (?\٧ "7a") + (?\٨ "8a") + (?\٩ "9a") + (?\ٰ "aS") + (?\پ "p+") + (?\ځ "hH") + (?\چ "tc") + (?\ژ "zj") + (?\ڤ "v+") + (?\گ "gf") + (?\۰ "0a") + (?\۱ "1a") + (?\۲ "2a") + (?\۳ "3a") + (?\۴ "4a") + (?\۵ "5a") + (?\۶ "6a") + (?\۷ "7a") + (?\۸ "8a") + (?\۹ "9a") + (?\ሀ "he") + (?\ሁ "hu") + (?\ሂ "hi") + (?\ሃ "ha") + (?\ሄ "hE") + (?\ህ "h") + (?\ሆ "ho") + (?\ለ "le") + (?\ሉ "lu") + (?\ሊ "li") + (?\ላ "la") + (?\ሌ "lE") + (?\ል "l") + (?\ሎ "lo") + (?\ሏ "lWa") + (?\ሐ "He") + (?\ሑ "Hu") + (?\ሒ "Hi") + (?\ሓ "Ha") + (?\ሔ "HE") + (?\ሕ "H") + (?\ሖ "Ho") + (?\ሗ "HWa") + (?\መ "me") + (?\ሙ "mu") + (?\ሚ "mi") + (?\ማ "ma") + (?\ሜ "mE") + (?\ም "m") + (?\ሞ "mo") + (?\ሟ "mWa") + (?\ሠ "`se") + (?\ሡ "`su") + (?\ሢ "`si") + (?\ሣ "`sa") + (?\ሤ "`sE") + (?\ሥ "`s") + (?\ሦ "`so") + (?\ሧ "`sWa") + (?\ረ "re") + (?\ሩ "ru") + (?\ሪ "ri") + (?\ራ "ra") + (?\ሬ "rE") + (?\ር "r") + (?\ሮ "ro") + (?\ሯ "rWa") + (?\ሰ "se") + (?\ሱ "su") + (?\ሲ "si") + (?\ሳ "sa") + (?\ሴ "sE") + (?\ስ "s") + (?\ሶ "so") + (?\ሷ "sWa") + (?\ሸ "xe") + (?\ሹ "xu") + (?\ሺ "xi") + (?\ሻ "xa") + (?\ሼ "xE") + (?\ሽ "xa") + (?\ሾ "xo") + (?\ሿ "xWa") + (?\ቀ "qe") + (?\ቁ "qu") + (?\ቂ "qi") + (?\ቃ "qa") + (?\ቄ "qE") + (?\ቅ "q") + (?\ቆ "qo") + (?\ቈ "qWe") + (?\ቊ "qWi") + (?\ቋ "qWa") + (?\ቌ "qWE") + (?\ቍ "qW") + (?\ቐ "Qe") + (?\ቑ "Qu") + (?\ቒ "Qi") + (?\ቓ "Qa") + (?\ቔ "QE") + (?\ቕ "Q") + (?\ቖ "Qo") + (?\ቘ "QWe") + (?\ቚ "QWi") + (?\ቛ "QWa") + (?\ቜ "QWE") + (?\ቝ "QW") + (?\በ "be") + (?\ቡ "bu") + (?\ቢ "bi") + (?\ባ "ba") + (?\ቤ "bE") + (?\ብ "b") + (?\ቦ "bo") + (?\ቧ "bWa") + (?\ቨ "ve") + (?\ቩ "vu") + (?\ቪ "vi") + (?\ቫ "va") + (?\ቬ "vE") + (?\ቭ "v") + (?\ቮ "vo") + (?\ቯ "vWa") + (?\ተ "te") + (?\ቱ "tu") + (?\ቲ "ti") + (?\ታ "ta") + (?\ቴ "tE") + (?\ት "t") + (?\ቶ "to") + (?\ቷ "tWa") + (?\ቸ "ce") + (?\ቹ "cu") + (?\ቺ "ci") + (?\ቻ "ca") + (?\ቼ "cE") + (?\ች "c") + (?\ቾ "co") + (?\ቿ "cWa") + (?\ኀ "`he") + (?\ኁ "`hu") + (?\ኂ "`hi") + (?\ኃ "`ha") + (?\ኄ "`hE") + (?\ኅ "`h") + (?\ኆ "`ho") + (?\ኈ "hWe") + (?\ኊ "hWi") + (?\ኋ "hWa") + (?\ኌ "hWE") + (?\ኍ "hW") + (?\ነ "na") + (?\ኑ "nu") + (?\ኒ "ni") + (?\ና "na") + (?\ኔ "nE") + (?\ን "n") + (?\ኖ "no") + (?\ኗ "nWa") + (?\ኘ "Ne") + (?\ኙ "Nu") + (?\ኚ "Ni") + (?\ኛ "Na") + (?\ኜ "NE") + (?\ኝ "N") + (?\ኞ "No") + (?\ኟ "NWa") + (?\አ "e") + (?\ኡ "u") + (?\ኢ "i") + (?\ኣ "a") + (?\ኤ "E") + (?\እ "I") + (?\ኦ "o") + (?\ኧ "e3") + (?\ከ "ke") + (?\ኩ "ku") + (?\ኪ "ki") + (?\ካ "ka") + (?\ኬ "kE") + (?\ክ "k") + (?\ኮ "ko") + (?\ኰ "kWe") + (?\ኲ "kWi") + (?\ኳ "kWa") + (?\ኴ "kWE") + (?\ኵ "kW") + (?\ኸ "Ke") + (?\ኹ "Ku") + (?\ኺ "Ki") + (?\ኻ "Ka") + (?\ኼ "KE") + (?\ኽ "K") + (?\ኾ "Ko") + (?\ዀ "KWe") + (?\ዂ "KWi") + (?\ዃ "KWa") + (?\ዄ "KWE") + (?\ዅ "KW") + (?\ወ "we") + (?\ዉ "wu") + (?\ዊ "wi") + (?\ዋ "wa") + (?\ዌ "wE") + (?\ው "w") + (?\ዎ "wo") + (?\ዐ "`e") + (?\ዑ "`u") + (?\ዒ "`i") + (?\ዓ "`a") + (?\ዔ "`E") + (?\ዕ "`I") + (?\ዖ "`o") + (?\ዘ "ze") + (?\ዙ "zu") + (?\ዚ "zi") + (?\ዛ "za") + (?\ዜ "zE") + (?\ዝ "z") + (?\ዞ "zo") + (?\ዟ "zWa") + (?\ዠ "Ze") + (?\ዡ "Zu") + (?\ዢ "Zi") + (?\ዣ "Za") + (?\ዤ "ZE") + (?\ዥ "Z") + (?\ዦ "Zo") + (?\ዧ "ZWa") + (?\የ "ye") + (?\ዩ "yu") + (?\ዪ "yi") + (?\ያ "ya") + (?\ዬ "yE") + (?\ይ "y") + (?\ዮ "yo") + (?\ዯ "yWa") + (?\ደ "de") + (?\ዱ "du") + (?\ዲ "di") + (?\ዳ "da") + (?\ዴ "dE") + (?\ድ "d") + (?\ዶ "do") + (?\ዷ "dWa") + (?\ዸ "De") + (?\ዹ "Du") + (?\ዺ "Di") + (?\ዻ "Da") + (?\ዼ "DE") + (?\ዽ "D") + (?\ዾ "Do") + (?\ዿ "DWa") + (?\ጀ "je") + (?\ጁ "ju") + (?\ጂ "ji") + (?\ጃ "ja") + (?\ጄ "jE") + (?\ጅ "j") + (?\ጆ "jo") + (?\ጇ "jWa") + (?\ገ "ga") + (?\ጉ "gu") + (?\ጊ "gi") + (?\ጋ "ga") + (?\ጌ "gE") + (?\ግ "g") + (?\ጎ "go") + (?\ጐ "gWu") + (?\ጒ "gWi") + (?\ጓ "gWa") + (?\ጔ "gWE") + (?\ጕ "gW") + (?\ጘ "Ge") + (?\ጙ "Gu") + (?\ጚ "Gi") + (?\ጛ "Ga") + (?\ጜ "GE") + (?\ጝ "G") + (?\ጞ "Go") + (?\ጟ "GWa") + (?\ጠ "Te") + (?\ጡ "Tu") + (?\ጢ "Ti") + (?\ጣ "Ta") + (?\ጤ "TE") + (?\ጥ "T") + (?\ጦ "To") + (?\ጧ "TWa") + (?\ጨ "Ce") + (?\ጩ "Ca") + (?\ጪ "Cu") + (?\ጫ "Ca") + (?\ጬ "CE") + (?\ጭ "C") + (?\ጮ "Co") + (?\ጯ "CWa") + (?\ጰ "Pe") + (?\ጱ "Pu") + (?\ጲ "Pi") + (?\ጳ "Pa") + (?\ጴ "PE") + (?\ጵ "P") + (?\ጶ "Po") + (?\ጷ "PWa") + (?\ጸ "SWe") + (?\ጹ "SWu") + (?\ጺ "SWi") + (?\ጻ "SWa") + (?\ጼ "SWE") + (?\ጽ "SW") + (?\ጾ "SWo") + (?\ጿ "SWa") + (?\ፀ "`Sa") + (?\ፁ "`Su") + (?\ፂ "`Si") + (?\ፃ "`Sa") + (?\ፄ "`SE") + (?\ፅ "`S") + (?\ፆ "`So") + (?\ፈ "fa") + (?\ፉ "fu") + (?\ፊ "fi") + (?\ፋ "fa") + (?\ፌ "fE") + (?\ፍ "o") + (?\ፎ "fo") + (?\ፏ "fWa") + (?\ፐ "pe") + (?\ፑ "pu") + (?\ፒ "pi") + (?\ፓ "pa") + (?\ፔ "pE") + (?\ፕ "p") + (?\ፖ "po") + (?\ፗ "pWa") + (?\ፘ "mYa") + (?\ፙ "rYa") + (?\ፚ "fYa") + (?\፠ " ") + (?\፡ ":") + (?\። "::") + (?\፣ ",") + (?\፤ ";") + (?\፥ "-:") + (?\፦ ":-") + (?\፧ "`?") + (?\፨ ":|:") + (?\፩ "`1") + (?\፪ "`2") + (?\፫ "`3") + (?\፬ "`4") + (?\፭ "`5") + (?\፮ "`6") + (?\፯ "`7") + (?\፰ "`8") + (?\፱ "`9") + (?\፲ "`10") + (?\፳ "`20") + (?\፴ "`30") + (?\፵ "`40") + (?\፶ "`50") + (?\፷ "`60") + (?\፸ "`70") + (?\፹ "`80") + (?\፺ "`90") + (?\፻ "`100") + (?\፼ "`10000") + (?\Ḁ "A-0") + (?\ḁ "a-0") + (?\Ḃ "B.") + (?\ḃ "b.") + (?\Ḅ "B-.") + (?\ḅ "b-.") + (?\Ḇ "B_") + (?\ḇ "b_") + (?\Ḉ "C,'") + (?\ḉ "c,'") + (?\Ḋ "D.") + (?\ḋ "d.") + (?\Ḍ "D-.") + (?\ḍ "d-.") + (?\Ḏ "D_") + (?\ḏ "d_") + (?\Ḑ "D,") + (?\ḑ "d,") + (?\Ḓ "D->") + (?\ḓ "d->") + (?\Ḕ "E-!") + (?\ḕ "e-!") + (?\Ḗ "E-'") + (?\ḗ "e-'") + (?\Ḙ "E->") + (?\ḙ "e->") + (?\Ḛ "E-?") + (?\ḛ "e-?") + (?\Ḝ "E,(") + (?\ḝ "e,(") + (?\Ḟ "F.") + (?\ḟ "f.") + (?\Ḡ "G-") + (?\ḡ "g-") + (?\Ḣ "H.") + (?\ḣ "h.") + (?\Ḥ "H-.") + (?\ḥ "h-.") + (?\Ḧ "H:") + (?\ḧ "h:") + (?\Ḩ "H,") + (?\ḩ "h,") + (?\Ḫ "H-(") + (?\ḫ "h-(") + (?\Ḭ "I-?") + (?\ḭ "i-?") + (?\Ḯ "I:'") + (?\ḯ "i:'") + (?\Ḱ "K'") + (?\ḱ "k'") + (?\Ḳ "K-.") + (?\ḳ "k-.") + (?\Ḵ "K_") + (?\ḵ "k_") + (?\Ḷ "L-.") + (?\ḷ "l-.") + (?\Ḹ "L--.") + (?\ḹ "l--.") + (?\Ḻ "L_") + (?\ḻ "l_") + (?\Ḽ "L->") + (?\ḽ "l->") + (?\Ḿ "M'") + (?\ḿ "m'") + (?\Ṁ "M.") + (?\ṁ "m.") + (?\Ṃ "M-.") + (?\ṃ "m-.") + (?\Ṅ "N.") + (?\ṅ "n.") + (?\Ṇ "N-.") + (?\ṇ "n-.") + (?\Ṉ "N_") + (?\ṉ "n_") + (?\Ṋ "N->") + (?\ṋ "n->") + (?\Ṍ "O?'") + (?\ṍ "o?'") + (?\Ṏ "O?:") + (?\ṏ "o?:") + (?\Ṑ "O-!") + (?\ṑ "o-!") + (?\Ṓ "O-'") + (?\ṓ "o-'") + (?\Ṕ "P'") + (?\ṕ "p'") + (?\Ṗ "P.") + (?\ṗ "p.") + (?\Ṙ "R.") + (?\ṙ "r.") + (?\Ṛ "R-.") + (?\ṛ "r-.") + (?\Ṝ "R--.") + (?\ṝ "r--.") + (?\Ṟ "R_") + (?\ṟ "r_") + (?\Ṡ "S.") + (?\ṡ "s.") + (?\Ṣ "S-.") + (?\ṣ "s-.") + (?\Ṥ "S'.") + (?\ṥ "s'.") + (?\Ṧ "S<.") + (?\ṧ "s<.") + (?\Ṩ "S.-.") + (?\ṩ "s.-.") + (?\Ṫ "T.") + (?\ṫ "t.") + (?\Ṭ "T-.") + (?\ṭ "t-.") + (?\Ṯ "T_") + (?\ṯ "t_") + (?\Ṱ "T->") + (?\ṱ "t->") + (?\Ṳ "U--:") + (?\ṳ "u--:") + (?\Ṵ "U-?") + (?\ṵ "u-?") + (?\Ṷ "U->") + (?\ṷ "u->") + (?\Ṹ "U?'") + (?\ṹ "u?'") + (?\Ṻ "U-:") + (?\ṻ "u-:") + (?\Ṽ "V?") + (?\ṽ "v?") + (?\Ṿ "V-.") + (?\ṿ "v-.") + (?\Ẁ "W!") + (?\ẁ "w!") + (?\Ẃ "W'") + (?\ẃ "w'") + (?\Ẅ "W:") + (?\ẅ "w:") + (?\Ẇ "W.") + (?\ẇ "w.") + (?\Ẉ "W-.") + (?\ẉ "w-.") + (?\Ẋ "X.") + (?\ẋ "x.") + (?\Ẍ "X:") + (?\ẍ "x:") + (?\Ẏ "Y.") + (?\ẏ "y.") + (?\Ẑ "Z>") + (?\ẑ "z>") + (?\Ẓ "Z-.") + (?\ẓ "z-.") + (?\Ẕ "Z_") + (?\ẕ "z_") + (?\ẖ "h_") + (?\ẗ "t:") + (?\ẘ "w0") + (?\ẙ "y0") + (?\Ạ "A-.") + (?\ạ "a-.") + (?\Ả "A2") + (?\ả "a2") + (?\Ấ "A>'") + (?\ấ "a>'") + (?\Ầ "A>!") + (?\ầ "a>!") + (?\Ẩ "A>2") + (?\ẩ "a>2") + (?\Ẫ "A>?") + (?\ẫ "a>?") + (?\Ậ "A>-.") + (?\ậ "a>-.") + (?\Ắ "A('") + (?\ắ "a('") + (?\Ằ "A(!") + (?\ằ "a(!") + (?\Ẳ "A(2") + (?\ẳ "a(2") + (?\Ẵ "A(?") + (?\ẵ "a(?") + (?\Ặ "A(-.") + (?\ặ "a(-.") + (?\Ẹ "E-.") + (?\ẹ "e-.") + (?\Ẻ "E2") + (?\ẻ "e2") + (?\Ẽ "E?") + (?\ẽ "e?") + (?\Ế "E>'") + (?\ế "e>'") + (?\Ề "E>!") + (?\ề "e>!") + (?\Ể "E>2") + (?\ể "e>2") + (?\Ễ "E>?") + (?\ễ "e>?") + (?\Ệ "E>-.") + (?\ệ "e>-.") + (?\Ỉ "I2") + (?\ỉ "i2") + (?\Ị "I-.") + (?\ị "i-.") + (?\Ọ "O-.") + (?\ọ "o-.") + (?\Ỏ "O2") + (?\ỏ "o2") + (?\Ố "O>'") + (?\ố "o>'") + (?\Ồ "O>!") + (?\ồ "o>!") + (?\Ổ "O>2") + (?\ổ "o>2") + (?\Ỗ "O>?") + (?\ỗ "o>?") + (?\Ộ "O>-.") + (?\ộ "o>-.") + (?\Ớ "O9'") + (?\ớ "o9'") + (?\Ờ "O9!") + (?\ờ "o9!") + (?\Ở "O92") + (?\ở "o92") + (?\Ỡ "O9?") + (?\ỡ "o9?") + (?\Ợ "O9-.") + (?\ợ "o9-.") + (?\Ụ "U-.") + (?\ụ "u-.") + (?\Ủ "U2") + (?\ủ "u2") + (?\Ứ "U9'") + (?\ứ "u9'") + (?\Ừ "U9!") + (?\ừ "u9!") + (?\Ử "U92") + (?\ử "u92") + (?\Ữ "U9?") + (?\ữ "u9?") + (?\Ự "U9-.") + (?\ự "u9-.") + (?\Ỳ "Y!") + (?\ỳ "y!") + (?\Ỵ "Y-.") + (?\ỵ "y-.") + (?\Ỷ "Y2") + (?\ỷ "y2") + (?\Ỹ "Y?") + (?\ỹ "y?") + (?\ἀ "a") + (?\ἁ "ha") + (?\ἂ "`a") + (?\ἃ "h`a") + (?\ἄ "a'") + (?\ἅ "ha'") + (?\ἆ "a~") + (?\ἇ "ha~") + (?\Ἀ "A") + (?\Ἁ "hA") + (?\Ἂ "`A") + (?\Ἃ "h`A") + (?\Ἄ "A'") + (?\Ἅ "hA'") + (?\Ἆ "A~") + (?\Ἇ "hA~") + (?\ἑ "he") + (?\Ἑ "hE") + (?\ἱ "hi") + (?\Ἱ "hI") + (?\ὁ "ho") + (?\Ὁ "hO") + (?\ὑ "hu") + (?\Ὑ "hU") + (?\᾿ ",,") + (?\῀ "?*") + (?\῁ "?:") + (?\῍ ",!") + (?\῎ ",'") + (?\῏ "?,") + (?\῝ ";!") + (?\῞ ";'") + (?\῟ "?;") + (?\ῥ "rh") + (?\Ῥ "Rh") + (?\῭ "!:") + (?\` "!*") + (?\῾ ";;") + (?\  " ") + (?\  " ") + (?\  " ") + (?\  " ") + (?\  " ") + (?\  " ") + (?\  " ") + (?\  " ") + (?\  " ") + (?\  " ") + (?\‐ "-") + (?\‑ "-") + (?\– "-") + (?\— "--") + (?\― "-") + (?\‖ "||") + (?\‗ "=2") + (?\‘ "`") + (?\’ "'") + (?\‚ "'") + (?\‛ "'") + (?\“ "\"") + (?\” "\"") + (?\„ "\"") + (?\‟ "\"") + (?\† "/-") + (?\‡ "/=") + (?\• " o ") + (?\․ ".") + (?\‥ "..") + (?\… "...") + (?\‧ "·") + (?\‰ " 0/00") + (?\′ "'") + (?\″ "''") + (?\‴ "'''") + (?\‵ "`") + (?\‶ "``") + (?\‷ "```") + (?\‸ "Ca") + (?\‹ "<") + (?\› ">") + (?\※ ":X") + (?\‼ "!!") + (?\‾ "'-") + (?\⁃ "-") + (?\⁄ "/") + (?\⁈ "?!") + (?\⁉ "!?") + (?\⁰ "^0") + (?\⁴ "^4") + (?\⁵ "^5") + (?\⁶ "^6") + (?\⁷ "^7") + (?\⁸ "^8") + (?\⁹ "^9") + (?\⁺ "^+") + (?\⁻ "^-") + (?\⁼ "^=") + (?\⁽ "^(") + (?\⁾ "^)") + (?\ⁿ "^n") + (?\₀ "_0") + (?\₁ "_1") + (?\₂ "_2") + (?\₃ "_3") + (?\₄ "_4") + (?\₅ "_5") + (?\₆ "_6") + (?\₇ "_7") + (?\₈ "_8") + (?\₉ "_9") + (?\₊ "_+") + (?\₋ "_-") + (?\₌ "_=") + (?\₍ "(") + (?\₎ ")") + (?\₣ "Ff") + (?\₤ "Li") + (?\₧ "Pt") + (?\₩ "W=") + (?\€ "EUR") + (?\℀ "a/c") + (?\℁ "a/s") + (?\℃ "oC") + (?\℅ "c/o") + (?\℆ "c/u") + (?\℉ "oF") + (?\ℊ "g") + (?\ℎ "h") + (?\ℏ "\\hbar") + (?\ℑ "Im") + (?\ℓ "l") + (?\№ "No.") + (?\℗ "PO") + (?\℘ "P") + (?\ℜ "Re") + (?\℞ "Rx") + (?\℠ "(SM)") + (?\℡ "TEL") + (?\™ "(TM)") + (?\Ω "Ohm") + (?\K "K") + (?\Å "Ang.") + (?\℮ "est.") + (?\ℴ "o") + (?\ℵ "Aleph ") + (?\ℶ "Bet ") + (?\ℷ "Gimel ") + (?\ℸ "Dalet ") + (?\⅓ " 1/3") + (?\⅔ " 2/3") + (?\⅕ " 1/5") + (?\⅖ " 2/5") + (?\⅗ " 3/5") + (?\⅘ " 4/5") + (?\⅙ " 1/6") + (?\⅚ " 5/6") + (?\⅛ " 1/8") + (?\⅜ " 3/8") + (?\⅝ " 5/8") + (?\⅞ " 7/8") + (?\⅟ " 1/") + (?\Ⅰ "I") + (?\Ⅱ "II") + (?\Ⅲ "III") + (?\Ⅳ "IV") + (?\Ⅴ "V") + (?\Ⅵ "VI") + (?\Ⅶ "VII") + (?\Ⅷ "VIII") + (?\Ⅸ "IX") + (?\Ⅹ "X") + (?\Ⅺ "XI") + (?\Ⅻ "XII") + (?\Ⅼ "L") + (?\Ⅽ "C") + (?\Ⅾ "D") + (?\Ⅿ "M") + (?\ⅰ "i") + (?\ⅱ "ii") + (?\ⅲ "iii") + (?\ⅳ "iv") + (?\ⅴ "v") + (?\ⅵ "vi") + (?\ⅶ "vii") + (?\ⅷ "viii") + (?\ⅸ "ix") + (?\ⅹ "x") + (?\ⅺ "xi") + (?\ⅻ "xii") + (?\ⅼ "l") + (?\ⅽ "c") + (?\ⅾ "d") + (?\ⅿ "m") + (?\ↀ "1000RCD") + (?\ↁ "5000R") + (?\ↂ "10000R") + (?\← "<-") + (?\↑ "-^") + (?\→ "->") + (?\↓ "-v") + (?\↔ "<->") + (?\↕ "UD") + (?\↖ "") + (?\↘ "!!>") + (?\↙ "V") + (?\⇐ "<=") + (?\⇑ "^^") + (?\⇒ "=>") + (?\⇓ "vv") + (?\⇔ "<=>") + (?\∀ "FA") + (?\∂ "\\partial") + (?\∃ "TE") + (?\∅ "{}") + (?\∆ "Delta") + (?\∇ "Nabla") + (?\∈ "(-") + (?\∉ "!(-") + (?\∊ "(-") + (?\∋ "-)") + (?\∌ "!-)") + (?\∍ "-)") + (?\∎ " qed") + (?\∏ "\\prod") + (?\∑ "\\sum") + (?\− " -") + (?\∓ "-/+") + (?\∔ ".+") + (?\∕ "/") + (?\∖ " - ") + (?\∗ "*") + (?\∘ " ° ") + (?\∙ "sb") + (?\√ " SQRT ") + (?\∛ " ROOT³ ") + (?\∜ " ROOT4 ") + (?\∝ "0(") + (?\∞ "infty") + (?\∟ "-L") + (?\∠ "-V") + (?\∥ "PP") + (?\∦ " !PP ") + (?\∧ "AND") + (?\∨ "OR") + (?\∩ "(U") + (?\∪ ")U") + (?\∫ "\\int ") + (?\∬ "DI") + (?\∮ "Io") + (?\∴ ".:") + (?\∵ ":.") + (?\∶ ":R") + (?\∷ "::") + (?\∼ "?1") + (?\∾ "CG") + (?\≃ "?-") + (?\≅ "?=") + (?\≈ "~=") + (?\≉ " !~= ") + (?\≌ "=?") + (?\≓ "HI") + (?\≔ ":=") + (?\≕ "=:") + (?\≠ "!=") + (?\≡ "=3") + (?\≢ " !=3 ") + (?\≤ "=<") + (?\≥ ">=") + (?\≦ ".LE.") + (?\≧ ".GE.") + (?\≨ ".LT.NOT.EQ.") + (?\≩ ".GT.NOT.EQ.") + (?\≪ "<<") + (?\≫ ">>") + (?\≮ "!<") + (?\≯ "!>") + (?\≶ " <> ") + (?\≷ " >< ") + (?\⊂ "(C") + (?\⊃ ")C") + (?\⊄ " !(C ") + (?\⊅ " !)C ") + (?\⊆ "(_") + (?\⊇ ")_") + (?\⊕ "(+)") + (?\⊖ "(-)") + (?\⊗ "(×)") + (?\⊘ "(/)") + (?\⊙ "(·)") + (?\⊚ "(°)") + (?\⊛ "(*)") + (?\⊜ "(=)") + (?\⊝ "(-)") + (?\⊞ "[+]") + (?\⊟ "[-]") + (?\⊠ "[×]") + (?\⊡ "[·]") + (?\⊥ "-T") + (?\⊧ " MODELS ") + (?\⊨ " TRUE ") + (?\⊩ " FORCES ") + (?\⊬ " !PROVES ") + (?\⊭ " NOT TRUE ") + (?\⊮ " !FORCES ") + (?\⊲ " NORMAL SUBGROUP OF ") + (?\⊳ " CONTAINS AS NORMAL SUBGROUP ") + (?\⊴ " NORMAL SUBGROUP OF OR EQUAL TO ") + (?\⊵ " CONTAINS AS NORMAL SUBGROUP OR EQUAL TO ") + (?\⊸ " MULTIMAP ") + (?\⊺ " INTERCALATE ") + (?\⊻ " XOR ") + (?\⊼ " NAND ") + (?\⋅ " · ") + (?\⋖ "<.") + (?\⋗ ">.") + (?\⋘ "<<<") + (?\⋙ ">>>") + (?\⋮ ":3") + (?\⋯ ".3") + (?\⌂ "Eh") + (?\⌇ "~~") + (?\⌈ "<7") + (?\⌉ ">7") + (?\⌊ "7<") + (?\⌋ "7>") + (?\⌐ "NI") + (?\⌒ "(A") + (?\⌕ "TR") + (?\⌘ "88") + (?\⌠ "Iu") + (?\⌡ "Il") + (?\⌢ ":(") + (?\⌣ ":)") + (?\⌤ "|^|") + (?\⌧ "[X]") + (?\〈 "") + (?\␣ "Vs") + (?\⑀ "1h") + (?\⑁ "3h") + (?\⑂ "2h") + (?\⑃ "4h") + (?\⑆ "1j") + (?\⑇ "2j") + (?\⑈ "3j") + (?\⑉ "4j") + (?\① "1-o") + (?\② "2-o") + (?\③ "3-o") + (?\④ "4-o") + (?\⑤ "5-o") + (?\⑥ "6-o") + (?\⑦ "7-o") + (?\⑧ "8-o") + (?\⑨ "9-o") + (?\⑩ "10-o") + (?\⑪ "11-o") + (?\⑫ "12-o") + (?\⑬ "13-o") + (?\⑭ "14-o") + (?\⑮ "15-o") + (?\⑯ "16-o") + (?\⑰ "17-o") + (?\⑱ "18-o") + (?\⑲ "19-o") + (?\⑳ "20-o") + (?\⑴ "(1)") + (?\⑵ "(2)") + (?\⑶ "(3)") + (?\⑷ "(4)") + (?\⑸ "(5)") + (?\⑹ "(6)") + (?\⑺ "(7)") + (?\⑻ "(8)") + (?\⑼ "(9)") + (?\⑽ "(10)") + (?\⑾ "(11)") + (?\⑿ "(12)") + (?\⒀ "(13)") + (?\⒁ "(14)") + (?\⒂ "(15)") + (?\⒃ "(16)") + (?\⒄ "(17)") + (?\⒅ "(18)") + (?\⒆ "(19)") + (?\⒇ "(20)") + (?\⒈ "1.") + (?\⒉ "2.") + (?\⒊ "3.") + (?\⒋ "4.") + (?\⒌ "5.") + (?\⒍ "6.") + (?\⒎ "7.") + (?\⒏ "8.") + (?\⒐ "9.") + (?\⒑ "10.") + (?\⒒ "11.") + (?\⒓ "12.") + (?\⒔ "13.") + (?\⒕ "14.") + (?\⒖ "15.") + (?\⒗ "16.") + (?\⒘ "17.") + (?\⒙ "18.") + (?\⒚ "19.") + (?\⒛ "20.") + (?\⒜ "(a)") + (?\⒝ "(b)") + (?\⒞ "(c)") + (?\⒟ "(d)") + (?\⒠ "(e)") + (?\⒡ "(f)") + (?\⒢ "(g)") + (?\⒣ "(h)") + (?\⒤ "(i)") + (?\⒥ "(j)") + (?\⒦ "(k)") + (?\⒧ "(l)") + (?\⒨ "(m)") + (?\⒩ "(n)") + (?\⒪ "(o)") + (?\⒫ "(p)") + (?\⒬ "(q)") + (?\⒭ "(r)") + (?\⒮ "(s)") + (?\⒯ "(t)") + (?\⒰ "(u)") + (?\⒱ "(v)") + (?\⒲ "(w)") + (?\⒳ "(x)") + (?\⒴ "(y)") + (?\⒵ "(z)") + (?\Ⓐ "A-o") + (?\Ⓑ "B-o") + (?\Ⓒ "C-o") + (?\Ⓓ "D-o") + (?\Ⓔ "E-o") + (?\Ⓕ "F-o") + (?\Ⓖ "G-o") + (?\Ⓗ "H-o") + (?\Ⓘ "I-o") + (?\Ⓙ "J-o") + (?\Ⓚ "K-o") + (?\Ⓛ "L-o") + (?\Ⓜ "M-o") + (?\Ⓝ "N-o") + (?\Ⓞ "O-o") + (?\Ⓟ "P-o") + (?\Ⓠ "Q-o") + (?\Ⓡ "R-o") + (?\Ⓢ "S-o") + (?\Ⓣ "T-o") + (?\Ⓤ "U-o") + (?\Ⓥ "V-o") + (?\Ⓦ "W-o") + (?\Ⓧ "X-o") + (?\Ⓨ "Y-o") + (?\Ⓩ "Z-o") + (?\ⓐ "a-o") + (?\ⓑ "b-o") + (?\ⓒ "c-o") + (?\ⓓ "d-o") + (?\ⓔ "e-o") + (?\ⓕ "f-o") + (?\ⓖ "g-o") + (?\ⓗ "h-o") + (?\ⓘ "i-o") + (?\ⓙ "j-o") + (?\ⓚ "k-o") + (?\ⓛ "l-o") + (?\ⓜ "m-o") + (?\ⓝ "n-o") + (?\ⓞ "o-o") + (?\ⓟ "p-o") + (?\ⓠ "q-o") + (?\ⓡ "r-o") + (?\ⓢ "s-o") + (?\ⓣ "t-o") + (?\ⓤ "u-o") + (?\ⓥ "v-o") + (?\ⓦ "w-o") + (?\ⓧ "x-o") + (?\ⓨ "y-o") + (?\ⓩ "z-o") + (?\⓪ "0-o") + (?\─ "-") + (?\━ "=") + (?\│ "|") + (?\┃ "|") + (?\┄ "-") + (?\┅ "=") + (?\┆ "|") + (?\┇ "|") + (?\┈ "-") + (?\┉ "=") + (?\┊ "|") + (?\┋ "|") + (?\┌ "+") + (?\┍ "+") + (?\┎ "+") + (?\┏ "+") + (?\┐ "+") + (?\┑ "+") + (?\┒ "+") + (?\┓ "+") + (?\└ "+") + (?\┕ "+") + (?\┖ "+") + (?\┗ "+") + (?\┘ "+") + (?\┙ "+") + (?\┚ "+") + (?\┛ "+") + (?\├ "+") + (?\┝ "+") + (?\┞ "+") + (?\┟ "+") + (?\┠ "+") + (?\┡ "+") + (?\┢ "+") + (?\┣ "+") + (?\┤ "+") + (?\┥ "+") + (?\┦ "+") + (?\┧ "+") + (?\┨ "+") + (?\┩ "+") + (?\┪ "+") + (?\┫ "+") + (?\┬ "+") + (?\┭ "+") + (?\┮ "+") + (?\┯ "+") + (?\┰ "+") + (?\┱ "+") + (?\┲ "+") + (?\┳ "+") + (?\┴ "+") + (?\┵ "+") + (?\┶ "+") + (?\┷ "+") + (?\┸ "+") + (?\┹ "+") + (?\┺ "+") + (?\┻ "+") + (?\┼ "+") + (?\┽ "+") + (?\┾ "+") + (?\┿ "+") + (?\╀ "+") + (?\╁ "+") + (?\╂ "+") + (?\╃ "+") + (?\╄ "+") + (?\╅ "+") + (?\╆ "+") + (?\╇ "+") + (?\╈ "+") + (?\╉ "+") + (?\╊ "+") + (?\╋ "+") + (?\╌ "+") + (?\╍ "+") + (?\╎ "+") + (?\╏ "+") + (?\═ "+") + (?\║ "+") + (?\╒ "+") + (?\╓ "+") + (?\╔ "+") + (?\╕ "+") + (?\╖ "+") + (?\╗ "+") + (?\╘ "+") + (?\╙ "+") + (?\╚ "+") + (?\╛ "+") + (?\╜ "+") + (?\╝ "+") + (?\╞ "+") + (?\╟ "+") + (?\╠ "+") + (?\╡ "+") + (?\╢ "+") + (?\╣ "+") + (?\╤ "+") + (?\╥ "+") + (?\╦ "+") + (?\╧ "+") + (?\╨ "+") + (?\╩ "+") + (?\╪ "+") + (?\╫ "+") + (?\╬ "+") + (?\╱ "/") + (?\╲ "\\") + (?\▀ "TB") + (?\▄ "LB") + (?\█ "FB") + (?\▌ "lB") + (?\▐ "RB") + (?\░ ".S") + (?\▒ ":S") + (?\▓ "?S") + (?\■ "fS") + (?\□ "OS") + (?\▢ "RO") + (?\▣ "Rr") + (?\▤ "RF") + (?\▥ "RY") + (?\▦ "RH") + (?\▧ "RZ") + (?\▨ "RK") + (?\▩ "RX") + (?\▪ "sB") + (?\▬ "SR") + (?\▭ "Or") + (?\▲ "^") + (?\△ "uT") + (?\▶ "|>") + (?\▷ "Tr") + (?\► "|>") + (?\▼ "v") + (?\▽ "dT") + (?\◀ "<|") + (?\◁ "Tl") + (?\◄ "<|") + (?\◆ "Db") + (?\◇ "Dw") + (?\◊ "LZ") + (?\○ "0m") + (?\◎ "0o") + (?\● "0M") + (?\◐ "0L") + (?\◑ "0R") + (?\◘ "Sn") + (?\◙ "Ic") + (?\◢ "Fd") + (?\◣ "Bd") + (?\◯ "Ci") + (?\★ "*2") + (?\☆ "*1") + (?\☎ "TEL") + (?\☏ "tel") + (?\☜ "<--") + (?\☞ "-->") + (?\☡ "CAUTION ") + (?\☧ "XP") + (?\☹ ":-(") + (?\☺ ":-)") + (?\☻ "(-:") + (?\☼ "SU") + (?\♀ "f.") + (?\♂ "m.") + (?\♠ "cS") + (?\♡ "cH") + (?\♢ "cD") + (?\♣ "cC") + (?\♤ "cS-") + (?\♥ "cH-") + (?\♦ "cD-") + (?\♧ "cC-") + (?\♩ "Md") + (?\♪ "M8") + (?\♫ "M2") + (?\♬ "M16") + (?\♭ "b") + (?\♮ "Mx") + (?\♯ "#") + (?\✓ "X") + (?\✗ "X") + (?\✠ "-X") + (?\  " ") + (?\、 ",_") + (?\。 "._") + (?\〃 "+\"") + (?\〄 "JIS") + (?\々 "*_") + (?\〆 ";_") + (?\〇 "0_") + (?\《 "<+") + (?\》 ">+") + (?\「 "<'") + (?\」 ">'") + (?\『 "<\"") + (?\』 ">\"") + (?\【 "(\"") + (?\】 ")\"") + (?\〒 "=T") + (?\〓 "=_") + (?\〔 "('") + (?\〕 ")'") + (?\〖 "(I") + (?\〗 ")I") + (?\〚 "[[") + (?\〛 "]]") + (?\〜 "-?") + (?\〠 "=T:)") + (?\〿 " ") + (?\ぁ "A5") + (?\あ "a5") + (?\ぃ "I5") + (?\い "i5") + (?\ぅ "U5") + (?\う "u5") + (?\ぇ "E5") + (?\え "e5") + (?\ぉ "O5") + (?\お "o5") + (?\か "ka") + (?\が "ga") + (?\き "ki") + (?\ぎ "gi") + (?\く "ku") + (?\ぐ "gu") + (?\け "ke") + (?\げ "ge") + (?\こ "ko") + (?\ご "go") + (?\さ "sa") + (?\ざ "za") + (?\し "si") + (?\じ "zi") + (?\す "su") + (?\ず "zu") + (?\せ "se") + (?\ぜ "ze") + (?\そ "so") + (?\ぞ "zo") + (?\た "ta") + (?\だ "da") + (?\ち "ti") + (?\ぢ "di") + (?\っ "tU") + (?\つ "tu") + (?\づ "du") + (?\て "te") + (?\で "de") + (?\と "to") + (?\ど "do") + (?\な "na") + (?\に "ni") + (?\ぬ "nu") + (?\ね "ne") + (?\の "no") + (?\は "ha") + (?\ば "ba") + (?\ぱ "pa") + (?\ひ "hi") + (?\び "bi") + (?\ぴ "pi") + (?\ふ "hu") + (?\ぶ "bu") + (?\ぷ "pu") + (?\へ "he") + (?\べ "be") + (?\ぺ "pe") + (?\ほ "ho") + (?\ぼ "bo") + (?\ぽ "po") + (?\ま "ma") + (?\み "mi") + (?\む "mu") + (?\め "me") + (?\も "mo") + (?\ゃ "yA") + (?\や "ya") + (?\ゅ "yU") + (?\ゆ "yu") + (?\ょ "yO") + (?\よ "yo") + (?\ら "ra") + (?\り "ri") + (?\る "ru") + (?\れ "re") + (?\ろ "ro") + (?\ゎ "wA") + (?\わ "wa") + (?\ゐ "wi") + (?\ゑ "we") + (?\を "wo") + (?\ん "n5") + (?\ゔ "vu") + (?\゛ "\"5") + (?\゜ "05") + (?\ゝ "*5") + (?\ゞ "+5") + (?\ァ "a6") + (?\ア "A6") + (?\ィ "i6") + (?\イ "I6") + (?\ゥ "u6") + (?\ウ "U6") + (?\ェ "e6") + (?\エ "E6") + (?\ォ "o6") + (?\オ "O6") + (?\カ "Ka") + (?\ガ "Ga") + (?\キ "Ki") + (?\ギ "Gi") + (?\ク "Ku") + (?\グ "Gu") + (?\ケ "Ke") + (?\ゲ "Ge") + (?\コ "Ko") + (?\ゴ "Go") + (?\サ "Sa") + (?\ザ "Za") + (?\シ "Si") + (?\ジ "Zi") + (?\ス "Su") + (?\ズ "Zu") + (?\セ "Se") + (?\ゼ "Ze") + (?\ソ "So") + (?\ゾ "Zo") + (?\タ "Ta") + (?\ダ "Da") + (?\チ "Ti") + (?\ヂ "Di") + (?\ッ "TU") + (?\ツ "Tu") + (?\ヅ "Du") + (?\テ "Te") + (?\デ "De") + (?\ト "To") + (?\ド "Do") + (?\ナ "Na") + (?\ニ "Ni") + (?\ヌ "Nu") + (?\ネ "Ne") + (?\ノ "No") + (?\ハ "Ha") + (?\バ "Ba") + (?\パ "Pa") + (?\ヒ "Hi") + (?\ビ "Bi") + (?\ピ "Pi") + (?\フ "Hu") + (?\ブ "Bu") + (?\プ "Pu") + (?\ヘ "He") + (?\ベ "Be") + (?\ペ "Pe") + (?\ホ "Ho") + (?\ボ "Bo") + (?\ポ "Po") + (?\マ "Ma") + (?\ミ "Mi") + (?\ム "Mu") + (?\メ "Me") + (?\モ "Mo") + (?\ャ "YA") + (?\ヤ "Ya") + (?\ュ "YU") + (?\ユ "Yu") + (?\ョ "YO") + (?\ヨ "Yo") + (?\ラ "Ra") + (?\リ "Ri") + (?\ル "Ru") + (?\レ "Re") + (?\ロ "Ro") + (?\ヮ "WA") + (?\ワ "Wa") + (?\ヰ "Wi") + (?\ヱ "We") + (?\ヲ "Wo") + (?\ン "N6") + (?\ヴ "Vu") + (?\ヵ "KA") + (?\ヶ "KE") + (?\ヷ "Va") + (?\ヸ "Vi") + (?\ヹ "Ve") + (?\ヺ "Vo") + (?\・ ".6") + (?\ー "-6") + (?\ヽ "*6") + (?\ヾ "+6") + (?\ㄅ "b4") + (?\ㄆ "p4") + (?\ㄇ "m4") + (?\ㄈ "f4") + (?\ㄉ "d4") + (?\ㄊ "t4") + (?\ㄋ "n4") + (?\ㄌ "l4") + (?\ㄍ "g4") + (?\ㄎ "k4") + (?\ㄏ "h4") + (?\ㄐ "j4") + (?\ㄑ "q4") + (?\ㄒ "x4") + (?\ㄓ "zh") + (?\ㄔ "ch") + (?\ㄕ "sh") + (?\ㄖ "r4") + (?\ㄗ "z4") + (?\ㄘ "c4") + (?\ㄙ "s4") + (?\ㄚ "a4") + (?\ㄛ "o4") + (?\ㄜ "e4") + (?\ㄝ "eh4") + (?\ㄞ "ai") + (?\ㄟ "ei") + (?\ㄠ "au") + (?\ㄡ "ou") + (?\ㄢ "an") + (?\ㄣ "en") + (?\ㄤ "aN") + (?\ㄥ "eN") + (?\ㄦ "er") + (?\ㄧ "i4") + (?\ㄨ "u4") + (?\ㄩ "iu") + (?\ㄪ "v4") + (?\ㄫ "nG") + (?\ㄬ "gn") + (?\㈜ "(JU)") + (?\㈠ "1c") + (?\㈡ "2c") + (?\㈢ "3c") + (?\㈣ "4c") + (?\㈤ "5c") + (?\㈥ "6c") + (?\㈦ "7c") + (?\㈧ "8c") + (?\㈨ "9c") + (?\㈩ "10c") + (?\㉿ "KSC") + (?\㏂ "am") + (?\㏘ "pm") + (?\ff "ff") + (?\fi "fi") + (?\fl "fl") + (?\ffi "ffi") + (?\ffl "ffl") + (?\ſt "St") + (?\st "st") + (?\ﹽ "3+;") + (?\ﺂ "aM.") + (?\ﺄ "aH.") + (?\ﺈ "ah.") + (?\ﺍ "a+-") + (?\ﺎ "a+.") + (?\ﺏ "b+-") + (?\ﺐ "b+.") + (?\ﺑ "b+,") + (?\ﺒ "b+;") + (?\ﺓ "tm-") + (?\ﺔ "tm.") + (?\ﺕ "t+-") + (?\ﺖ "t+.") + (?\ﺗ "t+,") + (?\ﺘ "t+;") + (?\ﺙ "tk-") + (?\ﺚ "tk.") + (?\ﺛ "tk,") + (?\ﺜ "tk;") + (?\ﺝ "g+-") + (?\ﺞ "g+.") + (?\ﺟ "g+,") + (?\ﺠ "g+;") + (?\ﺡ "hk-") + (?\ﺢ "hk.") + (?\ﺣ "hk,") + (?\ﺤ "hk;") + (?\ﺥ "x+-") + (?\ﺦ "x+.") + (?\ﺧ "x+,") + (?\ﺨ "x+;") + (?\ﺩ "d+-") + (?\ﺪ "d+.") + (?\ﺫ "dk-") + (?\ﺬ "dk.") + (?\ﺭ "r+-") + (?\ﺮ "r+.") + (?\ﺯ "z+-") + (?\ﺰ "z+.") + (?\ﺱ "s+-") + (?\ﺲ "s+.") + (?\ﺳ "s+,") + (?\ﺴ "s+;") + (?\ﺵ "sn-") + (?\ﺶ "sn.") + (?\ﺷ "sn,") + (?\ﺸ "sn;") + (?\ﺹ "c+-") + (?\ﺺ "c+.") + (?\ﺻ "c+,") + (?\ﺼ "c+;") + (?\ﺽ "dd-") + (?\ﺾ "dd.") + (?\ﺿ "dd,") + (?\ﻀ "dd;") + (?\ﻁ "tj-") + (?\ﻂ "tj.") + (?\ﻃ "tj,") + (?\ﻄ "tj;") + (?\ﻅ "zH-") + (?\ﻆ "zH.") + (?\ﻇ "zH,") + (?\ﻈ "zH;") + (?\ﻉ "e+-") + (?\ﻊ "e+.") + (?\ﻋ "e+,") + (?\ﻌ "e+;") + (?\ﻍ "i+-") + (?\ﻎ "i+.") + (?\ﻏ "i+,") + (?\ﻐ "i+;") + (?\ﻑ "f+-") + (?\ﻒ "f+.") + (?\ﻓ "f+,") + (?\ﻔ "f+;") + (?\ﻕ "q+-") + (?\ﻖ "q+.") + (?\ﻗ "q+,") + (?\ﻘ "q+;") + (?\ﻙ "k+-") + (?\ﻚ "k+.") + (?\ﻛ "k+,") + (?\ﻜ "k+;") + (?\ﻝ "l+-") + (?\ﻞ "l+.") + (?\ﻟ "l+,") + (?\ﻠ "l+;") + (?\ﻡ "m+-") + (?\ﻢ "m+.") + (?\ﻣ "m+,") + (?\ﻤ "m+;") + (?\ﻥ "n+-") + (?\ﻦ "n+.") + (?\ﻧ "n+,") + (?\ﻨ "n+;") + (?\ﻩ "h+-") + (?\ﻪ "h+.") + (?\ﻫ "h+,") + (?\ﻬ "h+;") + (?\ﻭ "w+-") + (?\ﻮ "w+.") + (?\ﻯ "j+-") + (?\ﻰ "j+.") + (?\ﻱ "y+-") + (?\ﻲ "y+.") + (?\ﻳ "y+,") + (?\ﻴ "y+;") + (?\ﻵ "lM-") + (?\ﻶ "lM.") + (?\ﻷ "lH-") + (?\ﻸ "lH.") + (?\ﻹ "lh-") + (?\ﻺ "lh.") + (?\ﻻ "la-") + (?\ﻼ "la.") + (?\! "!") + (?\" "\"") + (?\# "#") + (?\$ "$") + (?\% "%") + (?\& "&") + (?\' "'") + (?\( "(") + (?\) ")") + (?\* "*") + (?\+ "+") + (?\, ",") + (?\- "-") + (?\. ".") + (?\/ "/") + (?\0 "0") + (?\1 "1") + (?\2 "2") + (?\3 "3") + (?\4 "4") + (?\5 "5") + (?\6 "6") + (?\7 "7") + (?\8 "8") + (?\9 "9") + (?\: ":") + (?\; ";") + (?\< "<") + (?\= "=") + (?\> ">") + (?\? "?") + (?\@ "@") + (?\A "A") + (?\B "B") + (?\C "C") + (?\D "D") + (?\E "E") + (?\F "F") + (?\G "G") + (?\H "H") + (?\I "I") + (?\J "J") + (?\K "K") + (?\L "L") + (?\M "M") + (?\N "N") + (?\O "O") + (?\P "P") + (?\Q "Q") + (?\R "R") + (?\S "S") + (?\T "T") + (?\U "U") + (?\V "V") + (?\W "W") + (?\X "X") + (?\Y "Y") + (?\Z "Z") + (?\[ "[") + (?\\ "\\") + (?\] "]") + (?\^ "^") + (?\_ "_") + (?\` "`") + (?\a "a") + (?\b "b") + (?\c "c") + (?\d "d") + (?\e "e") + (?\f "f") + (?\g "g") + (?\h "h") + (?\i "i") + (?\j "j") + (?\k "k") + (?\l "l") + (?\m "m") + (?\n "n") + (?\o "o") + (?\p "p") + (?\q "q") + (?\r "r") + (?\s "s") + (?\t "t") + (?\u "u") + (?\v "v") + (?\w "w") + (?\x "x") + (?\y "y") + (?\z "z") + (?\{ "{") + (?\| "|") + (?\} "}") + (?\~ "~") + (?\。 ".") + (?\「 "\"") + (?\」 "\"") + (?\、 ",") + ;; Not from Lynx + (? "") + (?� "?")))) (aset standard-display-table (make-char 'mule-unicode-0100-24ff) nil) (aset standard-display-table commit 4efab4330e004774b0e5feaf1f2d2abc2183564a Author: Po Lu Date: Mon Jan 31 21:01:45 2022 +0800 ; * src/gtkutil.c (xg_create_frame_widgets): Avoid private GTK symbol. diff --git a/src/gtkutil.c b/src/gtkutil.c index b59bf4ebad..2b5f78aa32 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -1606,7 +1606,7 @@ xg_create_frame_widgets (struct frame *f) if (!visual) emacs_abort (); #else - GdkVisual *visual = gdk_screen_get_argb_visual (screen); + GdkVisual *visual = gdk_screen_get_rgba_visual (screen); #endif gtk_widget_set_visual (wtop, visual); commit 46473a4eac2579b88ec843e1301eb2a89835e2ae Author: Po Lu Date: Mon Jan 31 20:21:04 2022 +0800 Implement `alpha-background' on PGTK * src/ftcrfont.c (ftcrfont_draw): Respect alpha-background where appropriate. * src/gtkutil.c (xg_create_frame_widgets): Swap some conditionals around to get the right visual and signal handlers on PGTK. (xg_widget_style_updated): Likewise. * src/pgtkfns.c (pgtk_set_alpha_background): New function. (pgtk_frame_parm_handlers): Add it instead of the generic param handler. (Fx_create_frame): Fix typo. * src/pgtkterm.c (pgtk_fill_rectangle): (pgtk_set_cr_source_with_gc_foreground): (pgtk_set_cr_source_with_gc_background): (pgtk_set_cr_source_with_color): New argument `respect_alpha_backend'. All callers changed. * src/pgtkterm.h: Update function prototypes. diff --git a/src/ftcrfont.c b/src/ftcrfont.c index 558e44d5b9..c327146ba2 100644 --- a/src/ftcrfont.c +++ b/src/ftcrfont.c @@ -557,7 +557,7 @@ ftcrfont_draw (struct glyph_string *s, #ifdef HAVE_X_WINDOWS x_set_cr_source_with_gc_background (f, s->gc); #else - pgtk_set_cr_source_with_color (f, s->xgcv.background); + pgtk_set_cr_source_with_color (f, s->xgcv.background, true); #endif #else struct face *face = s->face; @@ -589,7 +589,7 @@ ftcrfont_draw (struct glyph_string *s, #ifdef HAVE_X_WINDOWS x_set_cr_source_with_gc_foreground (f, s->gc); #else - pgtk_set_cr_source_with_color (f, s->xgcv.foreground); + pgtk_set_cr_source_with_color (f, s->xgcv.foreground, false); #endif #else uint32_t col = s->hl == DRAW_CURSOR ? diff --git a/src/gtkutil.c b/src/gtkutil.c index b961cdedca..b59bf4ebad 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -81,11 +81,11 @@ static void xg_im_context_commit (GtkIMContext *, gchar *, gpointer); static void xg_im_context_preedit_changed (GtkIMContext *, gpointer); static void xg_im_context_preedit_end (GtkIMContext *, gpointer); static bool xg_widget_key_press_event_cb (GtkWidget *, GdkEvent *, gpointer); +#endif #if GTK_CHECK_VERSION (3, 10, 0) static void xg_widget_style_updated (GtkWidget *, gpointer); #endif -#endif #ifndef HAVE_GTK3 @@ -1464,13 +1464,6 @@ xg_create_frame_widgets (struct frame *f) } else wtop = gtk_window_new (type); - -#if GTK_CHECK_VERSION (3, 10, 0) - g_signal_connect (G_OBJECT (wtop), "style-updated", - G_CALLBACK (xg_widget_style_updated), f); -#endif - - gtk_widget_set_app_paintable (wtop, f->alpha_background != 1.0); #else if (f->tooltip) { @@ -1480,6 +1473,12 @@ xg_create_frame_widgets (struct frame *f) gtk_widget_add_events (wtop, GDK_ALL_EVENTS_MASK); #endif + gtk_widget_set_app_paintable (wtop, f->alpha_background != 1.0); +#if GTK_CHECK_VERSION (3, 10, 0) + g_signal_connect (G_OBJECT (wtop), "style-updated", + G_CALLBACK (xg_widget_style_updated), f); +#endif + /* gtk_window_set_has_resize_grip is a Gtk+ 3.0 function but Ubuntu has backported it to Gtk+ 2.0 and they add the resize grip for Gtk+ 2.0 applications also. But it has a bug that makes Emacs loop @@ -1606,10 +1605,12 @@ xg_create_frame_widgets (struct frame *f) if (!visual) emacs_abort (); +#else + GdkVisual *visual = gdk_screen_get_argb_visual (screen); +#endif gtk_widget_set_visual (wtop, visual); gtk_widget_set_visual (wfixed, visual); -#endif #ifndef HAVE_PGTK /* Must realize the windows so the X window gets created. It is used @@ -6398,6 +6399,7 @@ xg_filter_key (struct frame *frame, XEvent *xkey) return result; } +#endif #if GTK_CHECK_VERSION (3, 10, 0) static void @@ -6406,12 +6408,20 @@ xg_widget_style_updated (GtkWidget *widget, gpointer user_data) struct frame *f = user_data; if (f->alpha_background < 1.0) - XChangeProperty (FRAME_X_DISPLAY (f), - FRAME_X_WINDOW (f), - FRAME_DISPLAY_INFO (f)->Xatom_net_wm_opaque_region, - XA_CARDINAL, 32, PropModeReplace, - NULL, 0); -} + { +#ifndef HAVE_PGTK + XChangeProperty (FRAME_X_DISPLAY (f), + FRAME_X_WINDOW (f), + FRAME_DISPLAY_INFO (f)->Xatom_net_wm_opaque_region, + XA_CARDINAL, 32, PropModeReplace, + NULL, 0); +#else + if (FRAME_GTK_OUTER_WIDGET (f) + && gtk_widget_get_realized (FRAME_GTK_OUTER_WIDGET (f))) + gdk_window_set_opaque_region (gtk_widget_get_window (FRAME_GTK_OUTER_WIDGET (f)), + NULL); #endif + } +} #endif #endif /* USE_GTK */ diff --git a/src/pgtkfns.c b/src/pgtkfns.c index 5980b31d6e..c7987afc7d 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -234,6 +234,24 @@ x_set_background_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) unblock_input (); } +static void +pgtk_set_alpha_background (struct frame *f, Lisp_Object arg, Lisp_Object oldval) +{ + gui_set_alpha_background (f, arg, oldval); + + /* This prevents GTK from painting the window's background, which + interferes with transparent background in some environments */ + + gtk_widget_set_app_paintable (FRAME_GTK_OUTER_WIDGET (f), + f->alpha_background != 1.0); + + if (FRAME_GTK_OUTER_WIDGET (f) + && gtk_widget_get_realized (FRAME_GTK_OUTER_WIDGET (f)) + && f->alpha_background != 1.0) + gdk_window_set_opaque_region (gtk_widget_get_window (FRAME_GTK_OUTER_WIDGET (f)), + NULL); +} + static void x_set_border_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) { @@ -1043,7 +1061,7 @@ frame_parm_handler pgtk_frame_parm_handlers[] = { x_set_z_group, x_set_override_redirect, gui_set_no_special_glyphs, - gui_set_alpha_background, + pgtk_set_alpha_background, }; @@ -1668,7 +1686,7 @@ This function is an internal primitive--use `make-frame' instead. */ ) RES_TYPE_NUMBER); gui_default_parameter (f, parms, Qalpha, Qnil, "alpha", "Alpha", RES_TYPE_NUMBER); - gui_default_parameter (f, parms, Qalpha, Qnil, + gui_default_parameter (f, parms, Qalpha_background, Qnil, "alphaBackground", "AlphaBackground", RES_TYPE_NUMBER); if (!NILP (parent_frame)) diff --git a/src/pgtkterm.c b/src/pgtkterm.c index efbeaafaf1..9bb611e4c5 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -101,7 +101,8 @@ static void pgtk_delete_display (struct pgtk_display_info *dpyinfo); static void pgtk_clear_frame_area (struct frame *f, int x, int y, int width, int height); static void pgtk_fill_rectangle (struct frame *f, unsigned long color, int x, - int y, int width, int height); + int y, int width, int height, + bool respect_alpha_background); static void pgtk_clip_to_row (struct window *w, struct glyph_row *row, enum glyph_row_area area, cairo_t * cr); static struct frame *pgtk_any_window_to_frame (GdkWindow * window); @@ -1243,7 +1244,7 @@ pgtk_compute_glyph_string_overhangs (struct glyph_string *s) static void x_clear_glyph_string_rect (struct glyph_string *s, int x, int y, int w, int h) { - pgtk_fill_rectangle (s->f, s->xgcv.background, x, y, w, h); + pgtk_fill_rectangle (s->f, s->xgcv.background, x, y, w, h, true); } @@ -1328,13 +1329,13 @@ x_draw_glyph_string_background (struct glyph_string *s, bool force_p) static void pgtk_draw_rectangle (struct frame *f, unsigned long color, int x, int y, - int width, int height) + int width, int height, bool respect_alpha_background) { cairo_t *cr; cr = pgtk_begin_cr_clip (f); - pgtk_set_cr_source_with_color (f, color); - cairo_rectangle (cr, x + 0.5, y + 0.5, width, height); + pgtk_set_cr_source_with_color (f, color, true); + cairo_rectangle (cr, x + 0.5, y + 0.5, width, respect_alpha_background); cairo_set_line_width (cr, 1); cairo_stroke (cr); pgtk_end_cr_clip (f); @@ -1363,7 +1364,8 @@ x_draw_glyph_string_foreground (struct glyph_string *s) struct glyph *g = s->first_glyph + i; pgtk_draw_rectangle (s->f, s->face->foreground, x, s->y, - g->pixel_width - 1, s->height - 1); + g->pixel_width - 1, s->height - 1, + false); x += g->pixel_width; } } @@ -1413,7 +1415,7 @@ x_draw_composite_glyph_string_foreground (struct glyph_string *s) { if (s->cmp_from == 0) pgtk_draw_rectangle (s->f, s->face->foreground, x, s->y, - s->width - 1, s->height - 1); + s->width - 1, s->height - 1, false); } else if (!s->first_glyph->u.cmp.automatic) { @@ -1555,7 +1557,8 @@ x_draw_glyphless_glyph_string_foreground (struct glyph_string *s) pgtk_draw_rectangle (s->f, s->face->foreground, x, s->ybase - glyph->ascent, glyph->pixel_width - 1, - glyph->ascent + glyph->descent - 1); + glyph->ascent + glyph->descent - 1, + false); x += glyph->pixel_width; } } @@ -1658,7 +1661,7 @@ x_fill_trapezoid_for_relief (struct frame *f, unsigned long color, int x, cairo_t *cr; cr = pgtk_begin_cr_clip (f); - pgtk_set_cr_source_with_color (f, color); + pgtk_set_cr_source_with_color (f, color, false); cairo_move_to (cr, top_p ? x : x + height, y); cairo_line_to (cr, x, y + height); cairo_line_to (cr, top_p ? x + width - height : x + width, y + height); @@ -1685,7 +1688,7 @@ x_erase_corners_for_relief (struct frame *f, unsigned long color, int x, int i; cr = pgtk_begin_cr_clip (f); - pgtk_set_cr_source_with_color (f, color); + pgtk_set_cr_source_with_color (f, color, false); for (i = 0; i < CORNER_LAST; i++) if (corners & (1 << i)) { @@ -1818,7 +1821,7 @@ x_draw_relief_rect (struct frame *f, if (left_p) { pgtk_fill_rectangle (f, top_left_color, left_x, top_y, - vwidth, bottom_y + 1 - top_y); + vwidth, bottom_y + 1 - top_y, false); if (top_p) corners |= 1 << CORNER_TOP_LEFT; if (bot_p) @@ -1827,7 +1830,7 @@ x_draw_relief_rect (struct frame *f, if (right_p) { pgtk_fill_rectangle (f, bottom_right_color, right_x + 1 - vwidth, top_y, - vwidth, bottom_y + 1 - top_y); + vwidth, bottom_y + 1 - top_y, false); if (top_p) corners |= 1 << CORNER_TOP_RIGHT; if (bot_p) @@ -1837,7 +1840,7 @@ x_draw_relief_rect (struct frame *f, { if (!right_p) pgtk_fill_rectangle (f, top_left_color, left_x, top_y, - right_x + 1 - left_x, hwidth); + right_x + 1 - left_x, hwidth, false); else x_fill_trapezoid_for_relief (f, top_left_color, left_x, top_y, right_x + 1 - left_x, hwidth, 1); @@ -1847,7 +1850,7 @@ x_draw_relief_rect (struct frame *f, if (!left_p) pgtk_fill_rectangle (f, bottom_right_color, left_x, bottom_y + 1 - hwidth, right_x + 1 - left_x, - hwidth); + hwidth, false); else x_fill_trapezoid_for_relief (f, bottom_right_color, left_x, bottom_y + 1 - hwidth, @@ -1855,10 +1858,10 @@ x_draw_relief_rect (struct frame *f, } if (left_p && vwidth > 1) pgtk_fill_rectangle (f, bottom_right_color, left_x, top_y, - 1, bottom_y + 1 - top_y); + 1, bottom_y + 1 - top_y, false); if (top_p && hwidth > 1) pgtk_fill_rectangle (f, bottom_right_color, left_x, top_y, - right_x + 1 - left_x, 1); + right_x + 1 - left_x, 1, false); if (corners) { x_erase_corners_for_relief (f, FRAME_BACKGROUND_PIXEL (f), left_x, @@ -1893,23 +1896,25 @@ x_draw_box_rect (struct glyph_string *s, /* Top. */ pgtk_fill_rectangle (s->f, s->xgcv.foreground, - left_x, top_y, right_x - left_x + 1, hwidth); + left_x, top_y, right_x - left_x + 1, hwidth, + false); /* Left. */ if (left_p) pgtk_fill_rectangle (s->f, s->xgcv.foreground, - left_x, top_y, vwidth, bottom_y - top_y + 1); + left_x, top_y, vwidth, bottom_y - top_y + 1, + false); /* Bottom. */ pgtk_fill_rectangle (s->f, s->xgcv.foreground, left_x, bottom_y - hwidth + 1, right_x - left_x + 1, - hwidth); + hwidth, false); /* Right. */ if (right_p) pgtk_fill_rectangle (s->f, s->xgcv.foreground, right_x - vwidth + 1, top_y, vwidth, - bottom_y - top_y + 1); + bottom_y - top_y + 1, false); s->xgcv.foreground = foreground_backup; @@ -1979,7 +1984,7 @@ x_draw_horizontal_wave (struct frame *f, unsigned long color, int x, int y, int xoffset, n; cr = pgtk_begin_cr_clip (f); - pgtk_set_cr_source_with_color (f, color); + pgtk_set_cr_source_with_color (f, color, false); cairo_rectangle (cr, x, y, width, height); cairo_clip (cr); @@ -2155,7 +2160,7 @@ x_cr_draw_image (struct frame *f, Emacs_GC *gc, cairo_pattern_t *image, cairo_rectangle (cr, dest_x, dest_y, width, height); else { - pgtk_set_cr_source_with_gc_background (f, gc); + pgtk_set_cr_source_with_gc_background (f, gc, false); cairo_rectangle (cr, dest_x, dest_y, width, height); cairo_fill_preserve (cr); } @@ -2172,7 +2177,7 @@ x_cr_draw_image (struct frame *f, Emacs_GC *gc, cairo_pattern_t *image, } else { - pgtk_set_cr_source_with_gc_foreground (f, gc); + pgtk_set_cr_source_with_gc_foreground (f, gc, false); cairo_clip (cr); cairo_mask (cr, image); } @@ -2222,7 +2227,7 @@ x_draw_image_foreground (struct glyph_string *s) int relief = eabs (s->img->relief); pgtk_draw_rectangle (s->f, s->xgcv.foreground, x - relief, y - relief, s->slice.width + relief*2 - 1, - s->slice.height + relief*2 - 1); + s->slice.height + relief*2 - 1, false); } } pgtk_end_cr_clip (s->f); @@ -2230,7 +2235,7 @@ x_draw_image_foreground (struct glyph_string *s) else /* Draw a rectangle if image could not be loaded. */ pgtk_draw_rectangle (s->f, s->xgcv.foreground, x, y, - s->slice.width - 1, s->slice.height - 1); + s->slice.width - 1, s->slice.height - 1, false); } /* Draw image glyph string S. @@ -2375,7 +2380,8 @@ x_draw_stretch_glyph_string (struct glyph_string *s) } else { - pgtk_fill_rectangle (s->f, color, x, y, w, h); + pgtk_fill_rectangle (s->f, color, x, y, w, h, + false); } pgtk_end_cr_clip (s->f); @@ -2601,11 +2607,13 @@ pgtk_draw_glyph_string (struct glyph_string *s) y = s->ybase + position; if (s->face->underline_defaulted_p) pgtk_fill_rectangle (s->f, s->xgcv.foreground, - s->x, y, s->width, thickness); + s->x, y, s->width, thickness, + false); else { pgtk_fill_rectangle (s->f, s->face->underline_color, - s->x, y, s->width, thickness); + s->x, y, s->width, thickness, + false); } } } @@ -2616,11 +2624,11 @@ pgtk_draw_glyph_string (struct glyph_string *s) if (s->face->overline_color_defaulted_p) pgtk_fill_rectangle (s->f, s->xgcv.foreground, s->x, s->y + dy, - s->width, h); + s->width, h, false); else { pgtk_fill_rectangle (s->f, s->face->overline_color, s->x, - s->y + dy, s->width, h); + s->y + dy, s->width, h, false); } } @@ -2641,11 +2649,11 @@ pgtk_draw_glyph_string (struct glyph_string *s) if (s->face->strike_through_color_defaulted_p) pgtk_fill_rectangle (s->f, s->xgcv.foreground, s->x, glyph_y + dy, - s->width, h); + s->width, h, false); else { pgtk_fill_rectangle (s->f, s->face->strike_through_color, s->x, - glyph_y + dy, s->width, h); + glyph_y + dy, s->width, h, false); } } @@ -2778,7 +2786,7 @@ x_draw_hollow_cursor (struct window *w, struct glyph_row *row) /* The foreground of cursor_gc is typically the same as the normal background color, which can cause the cursor box to be invisible. */ cairo_t *cr = pgtk_begin_cr_clip (f); - pgtk_set_cr_source_with_color (f, FRAME_X_OUTPUT (f)->cursor_color); + pgtk_set_cr_source_with_color (f, FRAME_X_OUTPUT (f)->cursor_color, false); /* When on R2L character, show cursor at the right edge of the glyph, unless the cursor box is as wide as the glyph or wider @@ -2792,7 +2800,7 @@ x_draw_hollow_cursor (struct window *w, struct glyph_row *row) } /* Set clipping, draw the rectangle, and reset clipping again. */ pgtk_clip_to_row (w, row, TEXT_AREA, cr); - pgtk_draw_rectangle (f, FRAME_X_OUTPUT (f)->cursor_color, x, y, wd, h - 1); + pgtk_draw_rectangle (f, FRAME_X_OUTPUT (f)->cursor_color, x, y, wd, h - 1, false); pgtk_end_cr_clip (f); } @@ -2866,7 +2874,7 @@ x_draw_bar_cursor (struct window *w, struct glyph_row *row, int width, pgtk_fill_rectangle (f, color, x, WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y), - width, row->height); + width, row->height, false); } else /* HBAR_CURSOR */ { @@ -2887,7 +2895,7 @@ x_draw_bar_cursor (struct window *w, struct glyph_row *row, int width, pgtk_fill_rectangle (f, color, x, WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y + row->height - width), - w->phys_cursor_width - 1, width); + w->phys_cursor_width - 1, width, false); } pgtk_end_cr_clip (f); @@ -3241,7 +3249,7 @@ pgtk_draw_vertical_window_border (struct window *w, int x, int y0, int y1) face = FACE_FROM_ID_OR_NULL (f, VERTICAL_BORDER_FACE_ID); if (face) - pgtk_set_cr_source_with_color (f, face->foreground); + pgtk_set_cr_source_with_color (f, face->foreground, false); cairo_rectangle (cr, x, y0, 1, y1 - y0); cairo_fill (cr); @@ -3272,32 +3280,32 @@ pgtk_draw_window_divider (struct window *w, int x0, int x1, int y0, int y1) if (y1 - y0 > x1 - x0 && x1 - x0 > 2) /* Vertical. */ { - pgtk_set_cr_source_with_color (f, color_first); + pgtk_set_cr_source_with_color (f, color_first, false); cairo_rectangle (cr, x0, y0, 1, y1 - y0); cairo_fill (cr); - pgtk_set_cr_source_with_color (f, color); + pgtk_set_cr_source_with_color (f, color, false); cairo_rectangle (cr, x0 + 1, y0, x1 - x0 - 2, y1 - y0); cairo_fill (cr); - pgtk_set_cr_source_with_color (f, color_last); + pgtk_set_cr_source_with_color (f, color_last, false); cairo_rectangle (cr, x1 - 1, y0, 1, y1 - y0); cairo_fill (cr); } else if (x1 - x0 > y1 - y0 && y1 - y0 > 3) /* Horizontal. */ { - pgtk_set_cr_source_with_color (f, color_first); + pgtk_set_cr_source_with_color (f, color_first, false); cairo_rectangle (cr, x0, y0, x1 - x0, 1); cairo_fill (cr); - pgtk_set_cr_source_with_color (f, color); + pgtk_set_cr_source_with_color (f, color, false); cairo_rectangle (cr, x0, y0 + 1, x1 - x0, y1 - y0 - 2); cairo_fill (cr); - pgtk_set_cr_source_with_color (f, color_last); + pgtk_set_cr_source_with_color (f, color_last, false); cairo_rectangle (cr, x0, y1 - 1, x1 - x0, 1); cairo_fill (cr); } else { - pgtk_set_cr_source_with_color (f, color); + pgtk_set_cr_source_with_color (f, color, false); cairo_rectangle (cr, x0, y0, x1 - x0, y1 - y0); cairo_fill (cr); } @@ -3520,7 +3528,7 @@ pgtk_cr_draw_image (struct frame *f, Emacs_GC * gc, cairo_pattern_t * image, cairo_rectangle (cr, dest_x, dest_y, width, height); else { - pgtk_set_cr_source_with_gc_background (f, gc); + pgtk_set_cr_source_with_gc_background (f, gc, false); cairo_rectangle (cr, dest_x, dest_y, width, height); cairo_fill_preserve (cr); } @@ -3536,7 +3544,7 @@ pgtk_cr_draw_image (struct frame *f, Emacs_GC * gc, cairo_pattern_t * image, } else { - pgtk_set_cr_source_with_gc_foreground (f, gc); + pgtk_set_cr_source_with_gc_foreground (f, gc, false); cairo_clip (cr); cairo_mask (cr, image); } @@ -3568,7 +3576,7 @@ pgtk_draw_fringe_bitmap (struct window *w, struct glyph_row *row, } else { - pgtk_set_cr_source_with_color (f, face->background); + pgtk_set_cr_source_with_color (f, face->background, true); cairo_rectangle (cr, p->bx, p->by, p->nx, p->ny); cairo_fill (cr); } @@ -4970,11 +4978,11 @@ pgtk_handle_event (GtkWidget *widget, GdkEvent *event, gpointer *data) static void pgtk_fill_rectangle (struct frame *f, unsigned long color, int x, int y, - int width, int height) + int width, int height, bool respect_alpha_background) { cairo_t *cr; cr = pgtk_begin_cr_clip (f); - pgtk_set_cr_source_with_color (f, color); + pgtk_set_cr_source_with_color (f, color, respect_alpha_background); cairo_rectangle (cr, x, y, width, height); cairo_fill (cr); pgtk_end_cr_clip (f); @@ -6913,7 +6921,8 @@ pgtk_clear_area (struct frame *f, int x, int y, int width, int height) eassert (width > 0 && height > 0); cr = pgtk_begin_cr_clip (f); - pgtk_set_cr_source_with_color (f, FRAME_X_OUTPUT (f)->background_color); + pgtk_set_cr_source_with_color (f, FRAME_X_OUTPUT (f)->background_color, + true); cairo_rectangle (cr, x, y, width, height); cairo_fill (cr); pgtk_end_cr_clip (f); @@ -7095,25 +7104,39 @@ pgtk_end_cr_clip (struct frame *f) } void -pgtk_set_cr_source_with_gc_foreground (struct frame *f, Emacs_GC * gc) +pgtk_set_cr_source_with_gc_foreground (struct frame *f, Emacs_GC *gc, + bool respects_alpha_background) { - pgtk_set_cr_source_with_color (f, gc->foreground); + pgtk_set_cr_source_with_color (f, gc->foreground, + respects_alpha_background); } void -pgtk_set_cr_source_with_gc_background (struct frame *f, Emacs_GC * gc) +pgtk_set_cr_source_with_gc_background (struct frame *f, Emacs_GC *gc, + bool respects_alpha_background) { - pgtk_set_cr_source_with_color (f, gc->background); + pgtk_set_cr_source_with_color (f, gc->background, + respects_alpha_background); } void -pgtk_set_cr_source_with_color (struct frame *f, unsigned long color) +pgtk_set_cr_source_with_color (struct frame *f, unsigned long color, + bool respects_alpha_background) { Emacs_Color col; col.pixel = color; pgtk_query_color (f, &col); - cairo_set_source_rgb (FRAME_CR_CONTEXT (f), col.red / 65535.0, - col.green / 65535.0, col.blue / 65535.0); + + if (!respects_alpha_background) + cairo_set_source_rgb (FRAME_CR_CONTEXT (f), col.red / 65535.0, + col.green / 65535.0, col.blue / 65535.0); + else + { + cairo_set_source_rgba (FRAME_CR_CONTEXT (f), col.red / 65535.0, + col.green / 65535.0, col.blue / 65535.0, + f->alpha_background); + cairo_set_operator (FRAME_CR_CONTEXT (f), CAIRO_OPERATOR_SOURCE); + } } void diff --git a/src/pgtkterm.h b/src/pgtkterm.h index 42b03e315e..4d2285cdb0 100644 --- a/src/pgtkterm.h +++ b/src/pgtkterm.h @@ -591,12 +591,9 @@ extern void x_set_z_group (struct frame *f, Lisp_Object new_value, extern void pgtk_cr_update_surface_desired_size (struct frame *, int, int, bool); extern cairo_t *pgtk_begin_cr_clip (struct frame *f); extern void pgtk_end_cr_clip (struct frame *f); -extern void pgtk_set_cr_source_with_gc_foreground (struct frame *f, - Emacs_GC * gc); -extern void pgtk_set_cr_source_with_gc_background (struct frame *f, - Emacs_GC * gc); -extern void pgtk_set_cr_source_with_color (struct frame *f, - unsigned long color); +extern void pgtk_set_cr_source_with_gc_foreground (struct frame *, Emacs_GC *, bool); +extern void pgtk_set_cr_source_with_gc_background (struct frame *, Emacs_GC *, bool); +extern void pgtk_set_cr_source_with_color (struct frame *, unsigned long, bool); extern void pgtk_cr_draw_frame (cairo_t * cr, struct frame *f); extern void pgtk_cr_destroy_frame_context (struct frame *f); extern Lisp_Object pgtk_cr_export_frames (Lisp_Object frames, cairo_surface_type_t surface_type); commit 790ad61fcf91c75811ed30d21518e1dac99be044 Author: Po Lu Date: Mon Jan 31 18:37:09 2022 +0800 Fix accesses to GTK structures on tooltip frames * src/xfns.c (xic_set_preeditarea): Don't set the GTK context on tooltip frames. (x_set_alpha_background): Don't make tooltip frames paintable. * src/xterm.c (x_xr_ensure_picture): Get rid of GDK visual code. This is now done in a better way inside xg_create_frame_widgets. (bug#53654) diff --git a/src/xfns.c b/src/xfns.c index 656e68f099..7007f70b19 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -735,8 +735,10 @@ x_set_alpha_background (struct frame *f, Lisp_Object arg, Lisp_Object oldval) #ifdef USE_GTK /* This prevents GTK from painting the window's background, which interferes with transparent background in some environments */ - gtk_widget_set_app_paintable (FRAME_GTK_OUTER_WIDGET (f), - f->alpha_background != 1.0); + + if (!FRAME_TOOLTIP_P (f)) + gtk_widget_set_app_paintable (FRAME_GTK_OUTER_WIDGET (f), + f->alpha_background != 1.0); #endif if (f->alpha_background != 1.0) @@ -2870,6 +2872,9 @@ xic_set_preeditarea (struct window *w, int x, int y) XFree (attr); } #ifdef USE_GTK + if (f->tooltip) + return; + GdkRectangle rect; int scale = xg_get_scale (f); diff --git a/src/xterm.c b/src/xterm.c index 12f3c0a9d1..5bcb77bbeb 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -384,18 +384,7 @@ x_xr_ensure_picture (struct frame *f) { XRenderPictureAttributes attrs; attrs.clip_mask = None; - XRenderPictFormat *fmt; - -#ifdef USE_GTK - GdkWindow *wnd = gtk_widget_get_window (FRAME_GTK_OUTER_WIDGET (f)); - GdkVisual *visual = gdk_window_get_visual (wnd); - Visual *xvisual = gdk_x11_visual_get_xvisual (visual); - - fmt = XRenderFindVisualFormat (FRAME_X_DISPLAY (f), xvisual); - - if (!fmt) -#endif - fmt = FRAME_X_PICTURE_FORMAT (f); + XRenderPictFormat *fmt = FRAME_X_PICTURE_FORMAT (f); FRAME_X_PICTURE (f) = XRenderCreatePicture (FRAME_X_DISPLAY (f), FRAME_X_RAW_DRAWABLE (f), commit 2ce7ac1c502b1a362648d0a946c84659adf035e0 Author: Po Lu Date: Mon Jan 31 10:14:52 2022 +0000 * src/haikufns.c (Fx_display_visual_class): Return correct values. diff --git a/src/haikufns.c b/src/haikufns.c index 3b22f7bb37..8f5dae1a2b 100644 --- a/src/haikufns.c +++ b/src/haikufns.c @@ -1905,10 +1905,8 @@ DEFUN ("x-display-visual-class", Fx_display_visual_class, if (planes == 8) return intern ("static-color"); - else if (planes == 16 || planes == 15) - return intern ("pseudo-color"); - return intern ("direct-color"); + return intern ("true-color"); } DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0, commit 5edef4e98ce638069e37984537a9c5e5c7750667 Author: Po Lu Date: Mon Jan 31 18:13:19 2022 +0800 Improve portability of GDK visual code * src/gtkutil.c (xg_create_frame_widgets): Look up the visual instead of assuming it based on the depth. diff --git a/src/gtkutil.c b/src/gtkutil.c index ea9c91d316..b961cdedca 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -1601,12 +1601,14 @@ xg_create_frame_widgets (struct frame *f) GdkScreen *screen = gtk_widget_get_screen (wtop); #if !defined HAVE_PGTK - if (FRAME_DISPLAY_INFO (f)->n_planes == 32) - { - GdkVisual *visual = gdk_screen_get_rgba_visual (screen); - gtk_widget_set_visual (wtop, visual); - gtk_widget_set_visual (wfixed, visual); - } + GdkVisual *visual = gdk_x11_screen_lookup_visual (screen, + XVisualIDFromVisual (FRAME_X_VISUAL (f))); + + if (!visual) + emacs_abort (); + + gtk_widget_set_visual (wtop, visual); + gtk_widget_set_visual (wfixed, visual); #endif #ifndef HAVE_PGTK commit 1472b046eaeb8b2177341fb1c2b42bf5d1207ec7 Author: Po Lu Date: Mon Jan 31 18:08:07 2022 +0800 * src/xterm.c (x_term_init): Avoid freeze with 24-bit visuals. diff --git a/src/xterm.c b/src/xterm.c index dc4e53759e..12f3c0a9d1 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -15578,9 +15578,13 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) #ifdef HAVE_XRENDER if (dpyinfo->pict_format) { - get_bits_and_offset (((unsigned long) dpyinfo->pict_format->direct.alphaMask - << dpyinfo->pict_format->direct.alpha), - &dpyinfo->alpha_bits, &dpyinfo->alpha_offset); + unsigned long channel_mask + = ((unsigned long) dpyinfo->pict_format->direct.alphaMask + << dpyinfo->pict_format->direct.alpha); + + if (channel_mask) + get_bits_and_offset (channel_mask, &dpyinfo->alpha_bits, + &dpyinfo->alpha_offset); } else #endif commit 79896d3eb7f0d2e351196e5c896e21001b75f436 Author: Po Lu Date: Mon Jan 31 17:59:12 2022 +0800 Improve portability of alpha channel handling on TrueColor visuals * src/xfns.c (select_visual): Always ask for a TrueColor visual. * src/xfont.c (xfont_draw): * src/xftfont.c (xftfont_draw): Test `alpha_bits' instead of n_planes. * src/xterm.c (x_fill_rectangle, x_clear_rectangle): Likewise. (x_query_colors, x_alloc_nearest_color): Remove code that hard-coded alpha mask. (x_term_init): Calculate alpha bits and offset and populate field appropriately. * src/xterm.h (struct x_display_info): New fields `alpha_bits' and `alpha_offset'. (x_make_truecolor_pixel): Stop hardcoding the value of the alpha mask. diff --git a/src/xfns.c b/src/xfns.c index 8887b92241..656e68f099 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -6401,8 +6401,11 @@ select_visual (struct x_display_info *dpyinfo) /* First attempt to use 32-bit visual if available */ vinfo_template.depth = 32; + vinfo_template.class = TrueColor; - vinfo = XGetVisualInfo (dpy, VisualScreenMask | VisualDepthMask, + vinfo = XGetVisualInfo (dpy, (VisualScreenMask + | VisualDepthMask + | VisualClassMask), &vinfo_template, &n_visuals); if (n_visuals > 0) diff --git a/src/xfont.c b/src/xfont.c index 78f5f19bc8..684c28ab21 100644 --- a/src/xfont.c +++ b/src/xfont.c @@ -1005,7 +1005,7 @@ xfont_draw (struct glyph_string *s, int from, int to, int x, int y, #if defined HAVE_XRENDER && (RENDER_MAJOR > 0 || (RENDER_MINOR >= 2)) if (with_background - && FRAME_DISPLAY_INFO (s->f)->n_planes == 32 + && FRAME_DISPLAY_INFO (s->f)->alpha_bits && FRAME_CHECK_XR_VERSION (s->f, 0, 2)) { x_xr_ensure_picture (s->f); diff --git a/src/xftfont.c b/src/xftfont.c index cfbf7cdc7a..6a2b2086df 100644 --- a/src/xftfont.c +++ b/src/xftfont.c @@ -503,7 +503,7 @@ xftfont_draw (struct glyph_string *s, int from, int to, int x, int y, #if defined HAVE_XRENDER && (RENDER_MAJOR > 0 || (RENDER_MINOR >= 2)) if (with_background - && FRAME_DISPLAY_INFO (s->f)->n_planes == 32 + && FRAME_DISPLAY_INFO (s->f)->alpha_bits && FRAME_CHECK_XR_VERSION (s->f, 0, 2)) { x_xr_ensure_picture (s->f); diff --git a/src/xterm.c b/src/xterm.c index edafd88211..dc4e53759e 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -1356,7 +1356,7 @@ x_fill_rectangle (struct frame *f, GC gc, int x, int y, int width, int height, #else #if defined HAVE_XRENDER && (RENDER_MAJOR > 0 || (RENDER_MINOR >= 2)) if (respect_alpha_background - && FRAME_DISPLAY_INFO (f)->n_planes == 32 + && FRAME_DISPLAY_INFO (f)->alpha_bits && FRAME_CHECK_XR_VERSION (f, 0, 2)) { x_xr_ensure_picture (f); @@ -1398,7 +1398,7 @@ x_clear_rectangle (struct frame *f, GC gc, int x, int y, int width, int height, #else #if defined HAVE_XRENDER && (RENDER_MAJOR > 0 || (RENDER_MINOR >= 2)) if (respect_alpha_background - && FRAME_DISPLAY_INFO (f)->n_planes == 32 + && FRAME_DISPLAY_INFO (f)->alpha_bits && FRAME_CHECK_XR_VERSION (f, 0, 2)) { x_xr_ensure_picture (f); @@ -2976,12 +2976,6 @@ x_query_colors (struct frame *f, XColor *colors, int ncolors) colors[i].green = (g * gmult) >> 16; colors[i].blue = (b * bmult) >> 16; } - - if (FRAME_DISPLAY_INFO (f)->n_planes == 32) - { - for (i = 0; i < ncolors; ++i) - colors[i].pixel |= ((unsigned long) 0xFF << 24); - } return; } @@ -2999,12 +2993,6 @@ x_query_colors (struct frame *f, XColor *colors, int ncolors) } XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), colors, ncolors); - - if (FRAME_DISPLAY_INFO (f)->n_planes == 32) - { - for (i = 0; i < ncolors; ++i) - colors[i].pixel |= ((unsigned long) 0xFF << 24); - } } /* Store F's background color into *BGCOLOR. */ @@ -3158,7 +3146,9 @@ x_alloc_nearest_color (struct frame *f, Colormap cmap, XColor *color) gamma_correct (f, color); - if (dpyinfo->red_bits > 0) + if (dpyinfo->red_bits > 0 + && (dpyinfo->n_planes != 32 + || dpyinfo->alpha_bits > 0)) { color->pixel = x_make_truecolor_pixel (dpyinfo, color->red, @@ -15539,16 +15529,21 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) reset_mouse_highlight (&dpyinfo->mouse_highlight); - /* See if we can construct pixel values from RGB values. */ - if (dpyinfo->visual->class == TrueColor) +#ifdef HAVE_XRENDER + int event_base, error_base; + dpyinfo->xrender_supported_p + = XRenderQueryExtension (dpyinfo->display, &event_base, &error_base); + + if (dpyinfo->xrender_supported_p) { - get_bits_and_offset (dpyinfo->visual->red_mask, - &dpyinfo->red_bits, &dpyinfo->red_offset); - get_bits_and_offset (dpyinfo->visual->blue_mask, - &dpyinfo->blue_bits, &dpyinfo->blue_offset); - get_bits_and_offset (dpyinfo->visual->green_mask, - &dpyinfo->green_bits, &dpyinfo->green_offset); + if (!XRenderQueryVersion (dpyinfo->display, &dpyinfo->xrender_major, + &dpyinfo->xrender_minor)) + dpyinfo->xrender_supported_p = false; + else + dpyinfo->pict_format = XRenderFindVisualFormat (dpyinfo->display, + dpyinfo->visual); } +#endif /* See if a private colormap is requested. */ if (dpyinfo->visual == DefaultVisualOfScreen (dpyinfo->screen)) @@ -15570,6 +15565,46 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) dpyinfo->cmap = XCreateColormap (dpyinfo->display, dpyinfo->root_window, dpyinfo->visual, AllocNone); + /* See if we can construct pixel values from RGB values. */ + if (dpyinfo->visual->class == TrueColor) + { + get_bits_and_offset (dpyinfo->visual->red_mask, + &dpyinfo->red_bits, &dpyinfo->red_offset); + get_bits_and_offset (dpyinfo->visual->blue_mask, + &dpyinfo->blue_bits, &dpyinfo->blue_offset); + get_bits_and_offset (dpyinfo->visual->green_mask, + &dpyinfo->green_bits, &dpyinfo->green_offset); + +#ifdef HAVE_XRENDER + if (dpyinfo->pict_format) + { + get_bits_and_offset (((unsigned long) dpyinfo->pict_format->direct.alphaMask + << dpyinfo->pict_format->direct.alpha), + &dpyinfo->alpha_bits, &dpyinfo->alpha_offset); + } + else +#endif + { + XColor xc; + unsigned long alpha_mask; + xc.red = 65535; + xc.green = 65535; + xc.blue = 65535; + + if (XAllocColor (dpyinfo->display, + dpyinfo->cmap, &xc) != 0) + { + alpha_mask = xc.pixel & ~(dpyinfo->visual->red_mask + | dpyinfo->visual->blue_mask + | dpyinfo->visual->green_mask); + + if (alpha_mask) + get_bits_and_offset (alpha_mask, &dpyinfo->alpha_bits, + &dpyinfo->alpha_offset); + } + } + } + #ifdef HAVE_XDBE dpyinfo->supports_xdbe = false; int xdbe_major; @@ -15682,22 +15717,6 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) } #endif -#ifdef HAVE_XRENDER - int event_base, error_base; - dpyinfo->xrender_supported_p - = XRenderQueryExtension (dpyinfo->display, &event_base, &error_base); - - if (dpyinfo->xrender_supported_p) - { - if (!XRenderQueryVersion (dpyinfo->display, &dpyinfo->xrender_major, - &dpyinfo->xrender_minor)) - dpyinfo->xrender_supported_p = false; - else - dpyinfo->pict_format = XRenderFindVisualFormat (dpyinfo->display, - dpyinfo->visual); - } -#endif - #ifdef HAVE_XFIXES int xfixes_event_base, xfixes_error_base; dpyinfo->xfixes_supported_p diff --git a/src/xterm.h b/src/xterm.h index 5e17d5b721..c8c491a7d3 100644 --- a/src/xterm.h +++ b/src/xterm.h @@ -460,8 +460,8 @@ struct x_display_info int ncolor_cells; /* Bits and shifts to use to compose pixel values on TrueColor visuals. */ - int red_bits, blue_bits, green_bits; - int red_offset, blue_offset, green_offset; + int red_bits, blue_bits, green_bits, alpha_bits; + int red_offset, blue_offset, green_offset, alpha_offset; /* The type of window manager we have. If we move FRAME_OUTER_WINDOW to x/y 0/0, some window managers (type A) puts the window manager @@ -1285,8 +1285,11 @@ x_make_truecolor_pixel (struct x_display_info *dpyinfo, int r, int g, int b) pg = (g >> (16 - dpyinfo->green_bits)) << dpyinfo->green_offset; pb = (b >> (16 - dpyinfo->blue_bits)) << dpyinfo->blue_offset; - if (dpyinfo->n_planes == 32) - pa = ((unsigned long) 0xFF << 24); + if (dpyinfo->alpha_bits) + pa = (((unsigned long) 0xffff >> (16 - dpyinfo->alpha_bits)) + << dpyinfo->alpha_offset); + else + pa = 0; /* Assemble the pixel color. */ return pr | pg | pb | pa;