From 281b878858b381762ac74a96c85d383e8f423db9 Mon Sep 17 00:00:00 2001 From: Lars Ingebrigtsen Date: Fri, 14 Jan 2022 08:39:48 +0100 Subject: Mark test-map-into as unstable * test/lisp/emacs-lisp/map-tests.el (test-map-into): Mark as unstable (bug#46722). Do not merge to master. --- test/lisp/emacs-lisp/map-tests.el | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/lisp/emacs-lisp/map-tests.el b/test/lisp/emacs-lisp/map-tests.el index 314a1c9e302..31be0784ecb 100644 --- a/test/lisp/emacs-lisp/map-tests.el +++ b/test/lisp/emacs-lisp/map-tests.el @@ -422,6 +422,9 @@ Evaluate BODY for each created map." (should (map-every-p (lambda (k _v) (zerop k)) map)))) (ert-deftest test-map-into () + ;; This test is unstable in Emacs 28, but the problem has been fixed + ;; in Emacs 29 (bug#46722). + :tags '(:unstable) (let* ((plist '(a 1 b 2)) (alist '((a . 1) (b . 2))) (ht (map-into alist 'hash-table)) -- cgit v1.2.1 From c05864dd25c820fe250672d32d6ec77ba946670d Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Fri, 14 Jan 2022 16:11:34 +0200 Subject: Avoid another segfault in 'face_at_buffer_position' * src/xfaces.c (face_at_buffer_position): Make really sure the default face is usable. (Bug#53254) --- src/xfaces.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/xfaces.c b/src/xfaces.c index b9fb7c0ac1e..dff5ae346de 100644 --- a/src/xfaces.c +++ b/src/xfaces.c @@ -6425,8 +6425,12 @@ face_at_buffer_position (struct window *w, ptrdiff_t pos, default_face = FACE_FROM_ID_OR_NULL (f, face_id); if (!default_face) - default_face = FACE_FROM_ID (f, - lookup_basic_face (w, f, DEFAULT_FACE_ID)); + { + if (FRAME_FACE_CACHE (f)->used == 0) + recompute_basic_faces (f); + default_face = FACE_FROM_ID (f, + lookup_basic_face (w, f, DEFAULT_FACE_ID)); + } } /* Optimize common cases where we can use the default face. */ -- cgit v1.2.1 From c7234011518133da8b5f585719be511a1dfbcf11 Mon Sep 17 00:00:00 2001 From: Philipp Stephani Date: Fri, 14 Jan 2022 20:56:03 +0100 Subject: Simplify code for 'indent-for-tab-command' slightly. * lisp/indent.el (indent-for-tab-command): Don't use a one-element list for SYN. --- lisp/indent.el | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lisp/indent.el b/lisp/indent.el index 40669b38424..8dc4c31f135 100644 --- a/lisp/indent.el +++ b/lisp/indent.el @@ -170,7 +170,7 @@ prefix argument is ignored." (let ((old-tick (buffer-chars-modified-tick)) (old-point (point)) (old-indent (current-indentation)) - (syn `(,(syntax-after (point))))) + (syn (syntax-after (point)))) ;; Indent the line. (or (not (eq (indent--funcall-widened indent-line-function) 'noindent)) @@ -190,13 +190,13 @@ prefix argument is ignored." (eolp)) (and (member tab-first-completion '(word word-or-paren word-or-paren-or-punct)) - (not (member 2 syn))) + (not (eql 2 syn))) (and (member tab-first-completion '(word-or-paren word-or-paren-or-punct)) - (not (or (member 4 syn) - (member 5 syn)))) + (not (or (eql 4 syn) + (eql 5 syn)))) (and (equal tab-first-completion 'word-or-paren-or-punct) - (not (member 1 syn))))) + (not (eql 1 syn))))) (completion-at-point)) ;; If a prefix argument was given, rigidly indent the following -- cgit v1.2.1 From 64109fcae710a372bf7690e2da461ab71ca78dcd Mon Sep 17 00:00:00 2001 From: Philipp Stephani Date: Fri, 14 Jan 2022 20:59:28 +0100 Subject: indent-for-tab-command: Deal with large point or modiff values. * lisp/indent.el (indent-for-tab-command): Don't use 'eq' to compare integers that aren't guaranteed to be fixnums. --- lisp/indent.el | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lisp/indent.el b/lisp/indent.el index 8dc4c31f135..ad6fd899c55 100644 --- a/lisp/indent.el +++ b/lisp/indent.el @@ -182,8 +182,8 @@ prefix argument is ignored." (cond ;; If the text was already indented right, try completion. ((and (eq tab-always-indent 'complete) - (eq old-point (point)) - (eq old-tick (buffer-chars-modified-tick)) + (eql old-point (point)) + (eql old-tick (buffer-chars-modified-tick)) (or (null tab-first-completion) (eq last-command this-command) (and (equal tab-first-completion 'eol) -- cgit v1.2.1 From ec52d2775a9dc36ebac7bac9fc4bbfe42302fa80 Mon Sep 17 00:00:00 2001 From: Philipp Stephani Date: Fri, 14 Jan 2022 21:02:08 +0100 Subject: * lisp/indent.el (indent-for-tab-command): Use 'eq' for symbols. --- lisp/indent.el | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lisp/indent.el b/lisp/indent.el index ad6fd899c55..4e16d30ac92 100644 --- a/lisp/indent.el +++ b/lisp/indent.el @@ -186,16 +186,16 @@ prefix argument is ignored." (eql old-tick (buffer-chars-modified-tick)) (or (null tab-first-completion) (eq last-command this-command) - (and (equal tab-first-completion 'eol) + (and (eq tab-first-completion 'eol) (eolp)) - (and (member tab-first-completion - '(word word-or-paren word-or-paren-or-punct)) + (and (memq tab-first-completion + '(word word-or-paren word-or-paren-or-punct)) (not (eql 2 syn))) - (and (member tab-first-completion - '(word-or-paren word-or-paren-or-punct)) + (and (memq tab-first-completion + '(word-or-paren word-or-paren-or-punct)) (not (or (eql 4 syn) (eql 5 syn)))) - (and (equal tab-first-completion 'word-or-paren-or-punct) + (and (eq tab-first-completion 'word-or-paren-or-punct) (not (eql 1 syn))))) (completion-at-point)) -- cgit v1.2.1 From 0e20d76a384a65a238aa09fa00339a1b19496a15 Mon Sep 17 00:00:00 2001 From: Stefan Monnier Date: Fri, 14 Jan 2022 15:28:21 -0500 Subject: pcvs-info.el: Prefer `declare-function` over `autoload` * lisp/vc/pcvs-info.el (cvs-mode-toggle-mark): Use `declare-function` to silence the byte-compiler warning. --- lisp/vc/pcvs-info.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lisp/vc/pcvs-info.el b/lisp/vc/pcvs-info.el index 341fa243cfa..f5520e19ce6 100644 --- a/lisp/vc/pcvs-info.el +++ b/lisp/vc/pcvs-info.el @@ -130,7 +130,7 @@ to confuse some users sometimes." (defvar cvs-bakprefix ".#" "The prefix that CVS prepends to files when rcsmerge'ing.") -(autoload 'cvs-mode-toggle-mark "pcvs") +(declare-function 'cvs-mode-toggle-mark "pcvs" (e)) (defvar-keymap cvs-status-map :doc "Local keymap for text properties of status." -- cgit v1.2.1 From ac2cdb8a460243ab25aadc6baf5472d77abe070f Mon Sep 17 00:00:00 2001 From: Philipp Stephani Date: Fri, 14 Jan 2022 22:01:06 +0100 Subject: * lisp/progmodes/xref.el (xref-file-name-display): Fix docstring. --- lisp/progmodes/xref.el | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lisp/progmodes/xref.el b/lisp/progmodes/xref.el index 2311db426d4..0ee7dd5cadf 100644 --- a/lisp/progmodes/xref.el +++ b/lisp/progmodes/xref.el @@ -118,16 +118,16 @@ When it is a file name, it should be the \"expanded\" version.") (defcustom xref-file-name-display 'project-relative "Style of file name display in *xref* buffers. -If the value is the symbol `abs', the default, show the file names -in their full absolute form. +If the value is the symbol `abs', show the file names in their +full absolute form. If `nondirectory', show only the nondirectory (a.k.a. \"base name\") part of the file name. -If `project-relative', show only the file name relative to the -current project root. If there is no current project, or if the -file resides outside of its root, show that particular file name -in its full absolute form." +If `project-relative', the default, show only the file name +relative to the current project root. If there is no current +project, or if the file resides outside of its root, show that +particular file name in its full absolute form." :type '(choice (const :tag "absolute file name" abs) (const :tag "nondirectory file name" nondirectory) (const :tag "relative to project root" project-relative)) -- cgit v1.2.1 From 5990148860094bc3ad0ec55e4edac543d1c2036e Mon Sep 17 00:00:00 2001 From: Philipp Stephani Date: Fri, 14 Jan 2022 19:35:03 +0100 Subject: * lisp/simple.el (undo-no-redo): Fix customization group --- lisp/simple.el | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lisp/simple.el b/lisp/simple.el index ef7fdd061f7..355ebd690ff 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -2947,7 +2947,8 @@ undo record: if we undo from 4, `pending-undo-list' will be at 3, (defcustom undo-no-redo nil "If t, `undo' doesn't go through redo entries." - :type 'boolean) + :type 'boolean + :group 'undo) (defvar pending-undo-list nil "Within a run of consecutive undo commands, list remaining to be undone. -- cgit v1.2.1 From 1f5f3b7e8955154c28342e63ba1216f83ff6d73d Mon Sep 17 00:00:00 2001 From: Po Lu Date: Sat, 15 Jan 2022 09:11:11 +0800 Subject: Remove non-functional configure test It cannot work anymore, leading to compiler warnings when building xterm.c. * configure.ac: Remove test for whether XRegisterIMInstantiateCallback wants XPointer or XPointer * as the client_data. * src/xterm.c (xim_initialize): (xim_close_dpy): Just cast client data to void * and hope that the compiler keeps quiet. --- configure.ac | 35 ----------------------------------- src/xterm.c | 11 ++++++----- 2 files changed, 6 insertions(+), 40 deletions(-) diff --git a/configure.ac b/configure.ac index baf8c8018ec..955f0918fd4 100644 --- a/configure.ac +++ b/configure.ac @@ -3409,41 +3409,6 @@ if test "${with_xim}" != "no"; then [Define to 1 to default runtime use of XIM to on.]) fi - -if test "${HAVE_XIM}" != "no"; then - late_CFLAGS=$CFLAGS - if test "$GCC" = yes; then - CFLAGS="$CFLAGS --pedantic-errors" - fi - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ -#include -#include ]], -[[Display *display; -XrmDatabase db; -char *res_name; -char *res_class; -XIDProc *callback; -XPointer *client_data; -#ifndef __GNUC__ -/* If we're not using GCC, it's probably not XFree86, and this is - probably right, but we can't use something like --pedantic-errors. */ -extern Bool XRegisterIMInstantiateCallback(Display*, XrmDatabase, char*, - char*, XIMProc, XPointer*); -#endif -(void)XRegisterIMInstantiateCallback(display, db, res_name, res_class, callback, - client_data);]])], - [emacs_cv_arg6_star=yes]) - AH_TEMPLATE(XRegisterIMInstantiateCallback_arg6, - [Define to the type of the 6th arg of XRegisterIMInstantiateCallback, -either XPointer or XPointer*.])dnl - if test "$emacs_cv_arg6_star" = yes; then - AC_DEFINE(XRegisterIMInstantiateCallback_arg6, [XPointer*]) - else - AC_DEFINE(XRegisterIMInstantiateCallback_arg6, [XPointer]) - fi - CFLAGS=$late_CFLAGS -fi - # Check for XRender HAVE_XRENDER=no if test "${HAVE_X11}" = "yes"; then diff --git a/src/xterm.c b/src/xterm.c index ec415f5ffaf..103eb75a460 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -12698,9 +12698,11 @@ xim_initialize (struct x_display_info *dpyinfo, char *resource_name) ret = XRegisterIMInstantiateCallback (dpyinfo->display, dpyinfo->rdb, xim_inst->resource_name, emacs_class, xim_instantiate_callback, - /* This is XPointer in XFree86 but (XPointer *) - on Tru64, at least, hence the configure test. */ - (XRegisterIMInstantiateCallback_arg6) xim_inst); + /* This is XPointer in XFree86 but (XPointer *) on Tru64, at + least, but the configure test doesn't work because + xim_instantiate_callback can either be XIMProc or + XIDProc, so just cast to void *. */ + (void *) xim_inst); eassert (ret == True); #else /* not HAVE_X11R6_XIM */ xim_open_dpy (dpyinfo, resource_name); @@ -12725,8 +12727,7 @@ xim_close_dpy (struct x_display_info *dpyinfo) { Bool ret = XUnregisterIMInstantiateCallback (dpyinfo->display, dpyinfo->rdb, xim_inst->resource_name, - emacs_class, xim_instantiate_callback, - (XRegisterIMInstantiateCallback_arg6) xim_inst); + emacs_class, xim_instantiate_callback, (void *) xim_inst); eassert (ret == True); } xfree (xim_inst->resource_name); -- cgit v1.2.1 From 9845f6b9aa6e5ea0b272987bbf629d3eb4dc0531 Mon Sep 17 00:00:00 2001 From: Po Lu Date: Sat, 15 Jan 2022 09:40:28 +0800 Subject: Fix native input when using core input events * src/gtkutil.c (xg_filter_key): Test for core key press events correctly. * src/xterm.c (handle_one_xevent): Also check for KeyRelease events. --- src/gtkutil.c | 2 +- src/xterm.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/gtkutil.c b/src/gtkutil.c index 36ed55bc039..d17a6970b8d 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -6262,7 +6262,7 @@ xg_widget_key_press_event_cb (GtkWidget *widget, GdkEvent *event, bool xg_filter_key (struct frame *frame, XEvent *xkey) { - GdkEvent *xg_event = gdk_event_new ((xkey->type == ButtonPress + GdkEvent *xg_event = gdk_event_new ((xkey->type == KeyPress #ifdef HAVE_XINPUT2 || (xkey->type == GenericEvent && xkey->xgeneric.evtype == XI_KeyPress) diff --git a/src/xterm.c b/src/xterm.c index 103eb75a460..0e93c992751 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -8373,6 +8373,7 @@ x_filter_event (struct x_display_info *dpyinfo, XEvent *event) #ifdef USE_GTK } else if (f1 && (event->type == KeyPress + || event->type == KeyRelease #ifdef HAVE_XINPUT2 || xinput_event #endif -- cgit v1.2.1 From 9d809ed9bb778327b09c1ac10b1166df70ebd682 Mon Sep 17 00:00:00 2001 From: Po Lu Date: Sat, 15 Jan 2022 13:25:23 +0800 Subject: Filter key release events when using native input without having XIM * src/xterm.c (handle_one_xevent): Also check for XI key release events when using native input on a build without XIM. --- src/xterm.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/xterm.c b/src/xterm.c index 0e93c992751..5798ea3eebc 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -8435,8 +8435,10 @@ event_handler_gdk (GdkXEvent *gxev, GdkEvent *ev, gpointer data) && xev->type == GenericEvent && (xev->xgeneric.extension == dpyinfo->xi2_opcode) - && (xev->xgeneric.evtype - == XI_KeyPress)) + && ((xev->xgeneric.evtype + == XI_KeyPress) + || (xev->xgeneric.evtype + == XI_KeyRelease))) #endif )) { -- cgit v1.2.1 From 43618cd44c44568947732aacfe99919f25202343 Mon Sep 17 00:00:00 2001 From: Po Lu Date: Sat, 15 Jan 2022 05:30:28 +0000 Subject: Find a way to make lowering frames work on Haiku * doc/lispref/frames.texi (Raising and Lowering): Document that lowering frames is now supported on Haiku. * src/haikuterm.c (haiku_frame_raise_lower): Implement a hack to lower frames. --- doc/lispref/frames.texi | 6 ++---- src/haikuterm.c | 7 +++++++ 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/doc/lispref/frames.texi b/doc/lispref/frames.texi index ca7d9ada0ba..2eeb8b7ed74 100644 --- a/doc/lispref/frames.texi +++ b/doc/lispref/frames.texi @@ -3154,10 +3154,8 @@ raises @var{frame} above all other child frames of its parent. @deffn Command lower-frame &optional frame This function lowers frame @var{frame} (default, the selected frame) below all other frames belonging to the same or a higher z-group as -@var{frame}.@footnote{Lowering frames is not supported on Haiku, due -to limitations imposed by the system.} If @var{frame} is a child -frame (@pxref{Child Frames}), this lowers @var{frame} below all other -child frames of its parent. +@var{frame}. If @var{frame} is a child frame (@pxref{Child Frames}), +this lowers @var{frame} below all other child frames of its parent. @end deffn @defun frame-restack frame1 frame2 &optional above diff --git a/src/haikuterm.c b/src/haikuterm.c index 3e99cc1c8d9..ad89985b748 100644 --- a/src/haikuterm.c +++ b/src/haikuterm.c @@ -370,6 +370,13 @@ haiku_frame_raise_lower (struct frame *f, bool raise_p) BWindow_sync (FRAME_HAIKU_WINDOW (f)); unblock_input (); } + else + { + block_input (); + BWindow_send_behind (FRAME_HAIKU_WINDOW (f), NULL); + BWindow_sync (FRAME_HAIKU_WINDOW (f)); + unblock_input (); + } } /* Unfortunately, NOACTIVATE is not implementable on Haiku. */ -- cgit v1.2.1 From 639488b55a80e716e29dc74622c4c3e08ce3fbbc Mon Sep 17 00:00:00 2001 From: Lars Ingebrigtsen Date: Sat, 15 Jan 2022 09:06:50 +0100 Subject: Revert "Add command to invoke a search engine" This reverts commit 3f36d0836274a01d3cfc73f53ddbc76afc1d8a5e. Similar functionality has been added to webjump, so this commit duplicated that. --- lisp/mouse.el | 30 ------------------------------ 1 file changed, 30 deletions(-) diff --git a/lisp/mouse.el b/lisp/mouse.el index 46dd0397d7f..ad69d54fce4 100644 --- a/lisp/mouse.el +++ b/lisp/mouse.el @@ -534,16 +534,6 @@ Some context functions add menu items below the separator." :help "Find file or URL from text around mouse click")))) menu) -(defun context-menu-online-search (menu click) - "Populate MENU with command to search online." - (save-excursion - (mouse-set-point click) - (define-key-after menu [online-search-separator] menu-bar-separator) - (define-key-after menu [online-search-at-mouse] - '(menu-item "Online search" mouse-online-search-at-point - :help "Search for region or word online"))) - menu) - (defvar context-menu-entry `(menu-item ,(purecopy "Context Menu") ,(make-sparse-keymap) :filter ,(lambda (_) (context-menu-map))) @@ -3230,26 +3220,6 @@ is copied instead of being cut." (with-current-buffer (window-buffer window) (setq cursor-type (nth 3 state))))))) -(defvar eww-search-prefix) -(defun mouse-online-search-at-point (event) - "Query an online search engine at EVENT. -If a region is active, the entire region will be sent, otherwise -the symbol at point will be used. This command uses EWW's -default search engine, as configured by `eww-search-prefix'." - (interactive "e") - (require 'eww) - (let ((query (if (use-region-p) - (buffer-substring (region-beginning) - (region-end)) - (save-excursion - (mouse-set-point event) - (thing-at-point 'symbol))))) - (unless query - (user-error "Nothing to search for")) - (browse-url (concat - eww-search-prefix - (mapconcat #'url-hexify-string (split-string query) "+"))))) - ;;; Bindings for mouse commands. -- cgit v1.2.1 From 7651f044e26d5139d7140e0c4fd052893ef422d7 Mon Sep 17 00:00:00 2001 From: Lars Ingebrigtsen Date: Sat, 15 Jan 2022 09:30:01 +0100 Subject: Improve the with-output-to-temp-buffer doc string * lisp/subr.el (with-output-to-temp-buffer): Clarify the point of the macro (bug#53265). --- lisp/subr.el | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/lisp/subr.el b/lisp/subr.el index dd260dfe418..81c02338531 100644 --- a/lisp/subr.el +++ b/lisp/subr.el @@ -4294,11 +4294,13 @@ in which case `save-window-excursion' cannot help." (defmacro with-output-to-temp-buffer (bufname &rest body) "Bind `standard-output' to buffer BUFNAME, eval BODY, then show that buffer. -This construct makes buffer BUFNAME empty before running BODY. -It does not make the buffer current for BODY. -Instead it binds `standard-output' to that buffer, so that output -generated with `prin1' and similar functions in BODY goes into -the buffer. +This is a convenience macro meant for displaying help buffers and +the like. It empties the BUFNAME buffer before evaluating BODY +and disables undo in that buffer. + +It does not make the buffer current for BODY. Instead it binds +`standard-output' to that buffer, so that output generated with +`prin1' and similar functions in BODY goes into the buffer. At the end of BODY, this marks buffer BUFNAME unmodified and displays it in a window, but does not select it. The normal way to do this is -- cgit v1.2.1 From f501d0aed00998feb28c6f716e50f22a326b558c Mon Sep 17 00:00:00 2001 From: Alex Bochannek Date: Sat, 15 Jan 2022 10:28:14 +0100 Subject: (gnus-summary-hide-thread): Fix thread hiding for dummy roots. * lisp/gnus/gnus-sum.el (gnus-summary-hide-thread): Make thread hiding work when using dummy `gnus-summary-make-false-root' (bug#52923). --- lisp/gnus/gnus-sum.el | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lisp/gnus/gnus-sum.el b/lisp/gnus/gnus-sum.el index d3e476b5d64..6dfdcaf55c7 100644 --- a/lisp/gnus/gnus-sum.el +++ b/lisp/gnus/gnus-sum.el @@ -11898,7 +11898,8 @@ Returns nil if no threads were there to be hidden." (beginning-of-line) (let ((start (point)) (starteol (line-end-position)) - (article (gnus-summary-article-number))) + (article (unless (gnus-summary-article-intangible-p) + (gnus-summary-article-number)))) ;; Go forward until either the buffer ends or the subthread ends. (when (and (not (eobp)) (or (zerop (gnus-summary-next-thread 1 t)) @@ -11912,7 +11913,9 @@ Returns nil if no threads were there to be hidden." (let ((ol (make-overlay starteol (point) nil t nil))) (overlay-put ol 'invisible 'gnus-sum) (overlay-put ol 'evaporate t))) - (gnus-summary-goto-subject article) + (if article + (gnus-summary-goto-subject article) + (gnus-summary-position-point)) ;; We moved backward past the start point (invisible thread?) (when (> start (point)) (goto-char starteol))) -- cgit v1.2.1 From ad3971f885858dd6513e307a9eaa710bbad0e03a Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Sat, 15 Jan 2022 10:30:24 +0100 Subject: Use "server complete" instead of "complete" in gud-gdb-completions * lisp/progmodes/gud.el (gud-gdb-completions): gud-gdb sends a "complete" command to gdb to implement command line completion. It would be better to send "server complete". This is what Emacs does for other behind-the-scenes commands it sends (bug#52922). --- lisp/progmodes/gud.el | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lisp/progmodes/gud.el b/lisp/progmodes/gud.el index 3f78c9eb15b..b42279415bc 100644 --- a/lisp/progmodes/gud.el +++ b/lisp/progmodes/gud.el @@ -869,7 +869,8 @@ the buffer in which this command was invoked." COMMAND is the prefix for which we seek completion. CONTEXT is the text before COMMAND on the line." (let* ((complete-list - (gud-gdb-run-command-fetch-lines (concat "complete " context command) + (gud-gdb-run-command-fetch-lines (concat "server complete " + context command) (current-buffer) ;; From string-match above. (length context)))) -- cgit v1.2.1 From f43b8f3831951dfc93e99b2c9f0eeb8f6126ca88 Mon Sep 17 00:00:00 2001 From: Lars Ingebrigtsen Date: Sat, 15 Jan 2022 10:40:39 +0100 Subject: Don't bug out on improper lists in pp-emacs-lisp-code * lisp/emacs-lisp/pp.el (pp--format-list): Don't bug out on improper lists (bug#52917). --- lisp/emacs-lisp/pp.el | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lisp/emacs-lisp/pp.el b/lisp/emacs-lisp/pp.el index d199716b2c5..e782cdb1dab 100644 --- a/lisp/emacs-lisp/pp.el +++ b/lisp/emacs-lisp/pp.el @@ -273,7 +273,10 @@ Use the `pp-max-width' variable to control the desired line length." (insert "(") (pp--insert start (pop sexp)) (while sexp - (pp--insert " " (pop sexp))) + (if (consp sexp) + (pp--insert " " (pop sexp)) + (pp--insert " . " sexp) + (setq sexp nil))) (insert ")"))) (defun pp--format-function (sexp) -- cgit v1.2.1 From 3b27edd5f5fe4f9f45f1dd54ec24dcc6181ddca9 Mon Sep 17 00:00:00 2001 From: Po Lu Date: Sat, 15 Jan 2022 18:11:35 +0800 Subject: * src/emacsgtkfixed.c (XSetWMSizeHints): Remove some useless code. --- src/emacsgtkfixed.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/emacsgtkfixed.c b/src/emacsgtkfixed.c index da56031e2a4..a38ba35ad80 100644 --- a/src/emacsgtkfixed.c +++ b/src/emacsgtkfixed.c @@ -164,13 +164,9 @@ XSetWMSizeHints (Display *d, if ((hints->flags & PMinSize) && f) { -#ifdef HAVE_PGTK - int w = f->output_data.pgtk->size_hints.min_width; - int h = f->output_data.pgtk->size_hints.min_height; -#else int w = f->output_data.x->size_hints.min_width; int h = f->output_data.x->size_hints.min_height; -#endif + data[5] = w; data[6] = h; } -- cgit v1.2.1 From 7a679953e22ada9df02b181b872b9e56bbfd0f07 Mon Sep 17 00:00:00 2001 From: Po Lu Date: Sat, 15 Jan 2022 18:18:34 +0800 Subject: Prevent pre-edit overlay text from being displayed after a command This works around buggy input methods causing the overlay to be displayed alongside newly inserted text for a brief period. * lisp/term/x-win.el (x-clear-preedit-text): New function. (x-preedit-text): Add said function to pre-command-hook. It will remove itself when triggered. --- lisp/term/x-win.el | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/lisp/term/x-win.el b/lisp/term/x-win.el index e52e488edab..cd63c9208ba 100644 --- a/lisp/term/x-win.el +++ b/lisp/term/x-win.el @@ -1527,16 +1527,32 @@ This uses `icon-map-list' to map icon file names to stock icon names." (defvar x-preedit-overlay nil "The overlay currently used to display preedit text from a compose sequence.") +;; With some input methods, text gets inserted before Emacs is told to +;; remove any preedit text that was displayed, which causes both the +;; preedit overlay and the text to be visible for a brief period of +;; time. This pre-command-hook clears the overlay before any command +;; and should be set whenever a preedit overlay is visible. +(defun x-clear-preedit-text () + "Clear the pre-edit overlay and remove itself from pre-command-hook. +This function should be installed in `pre-command-hook' whenever +preedit text is displayed." + (when x-preedit-overlay + (delete-overlay x-preedit-overlay) + (setq x-preedit-overlay nil)) + (remove-hook 'pre-command-hook #'x-clear-preedit-text)) + (defun x-preedit-text (event) "Display preedit text from a compose sequence in EVENT. EVENT is a preedit-text event." (interactive "e") (when x-preedit-overlay (delete-overlay x-preedit-overlay) - (setq x-preedit-overlay nil)) + (setq x-preedit-overlay nil) + (remove-hook 'pre-command-hook #'x-clear-preedit-text)) (when (nth 1 event) (let ((string (propertize (nth 1 event) 'face '(:underline t)))) (setq x-preedit-overlay (make-overlay (point) (point))) + (add-hook 'pre-command-hook #'x-clear-preedit-text) (overlay-put x-preedit-overlay 'window (selected-window)) (overlay-put x-preedit-overlay 'before-string (if x-display-cursor-at-start-of-preedit-string -- cgit v1.2.1 From 45f1e427fc8b5722b1179eff6375d3da24299ddc Mon Sep 17 00:00:00 2001 From: Tassilo Horn Date: Sat, 15 Jan 2022 11:23:46 +0100 Subject: mailcap: Docfix & handle function-viewer case in mailcap-view-file * lisp/net/mailcap.el (mailcap-mime-data): Fix docstring: if viewer is a symbol/function, it should have zero args and expect the file's contents to be in the current buffer. (mailcap-view-file): Implement the case where the chosen viewer is a function and not a shell command. --- lisp/net/mailcap.el | 72 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 42 insertions(+), 30 deletions(-) diff --git a/lisp/net/mailcap.el b/lisp/net/mailcap.el index daa2d5a3fb3..b65f7c25b83 100644 --- a/lisp/net/mailcap.el +++ b/lisp/net/mailcap.el @@ -319,8 +319,9 @@ attribute name (viewer, test, etc). This looks like: Where VIEWERINFO specifies how the content-type is viewed. Can be a string, in which case it is run through a shell, with appropriate -parameters, or a symbol, in which case the symbol is `funcall'ed if -and only if it exists as a function, with the buffer as an argument. +parameters, or a symbol, in which case the symbol must name a function +of zero arguments which is called in a buffer holding the MIME part's +content. TESTINFO is a test for the viewer's applicability, or nil. If nil, it means the viewer is always valid. If it is a Lisp function, it is @@ -1175,34 +1176,45 @@ See \"~/.mailcap\", `mailcap-mime-data' and related files and variables." (mailcap-parse-mailcaps) (let ((command (mailcap-mime-info (mailcap-extension-to-mime (file-name-extension file))))) - (unless command - (error "No viewer for %s" (file-name-extension file))) - ;; Remove quotes around the file name - we'll use shell-quote-argument. - (while (string-match "['\"]%s['\"]" command) - (setq command (replace-match "%s" t t command))) - (setq command (replace-regexp-in-string - "%s" - (shell-quote-argument (convert-standard-filename file)) - command - nil t)) - ;; Handlers such as "gio open" and kde-open5 start viewer in background - ;; and exit immediately. Avoid `start-process' since it assumes - ;; :connection-type `pty' and kills children processes with SIGHUP - ;; when temporary terminal session is finished (Bug#44824). - ;; An alternative is `process-connection-type' let-bound to nil for - ;; `start-process-shell-command' call (with no chance to report failure). - (make-process - :name "mailcap-view-file" - :connection-type 'pipe - :buffer nil ; "*Messages*" may be suitable for debugging - :sentinel (lambda (proc event) - (when (and (memq (process-status proc) '(exit signal)) - (/= (process-exit-status proc) 0)) - (message - "Command %s: %s." - (mapconcat #'identity (process-command proc) " ") - (substring event 0 -1)))) - :command (list shell-file-name shell-command-switch command)))) + (if (functionp command) + ;; command is a viewer function (a mode) expecting the file + ;; contents to be in the current buffer. + (let ((buf (generate-new-buffer (file-name-nondirectory file)))) + (set-buffer buf) + (insert-file-contents file) + (setq buffer-file-name file) + (funcall command) + (set-buffer-modified-p nil) + (pop-to-buffer buf)) + ;; command is a program to run with file as an argument. + (unless command + (error "No viewer for %s" (file-name-extension file))) + ;; Remove quotes around the file name - we'll use shell-quote-argument. + (while (string-match "['\"]%s['\"]" command) + (setq command (replace-match "%s" t t command))) + (setq command (replace-regexp-in-string + "%s" + (shell-quote-argument (convert-standard-filename file)) + command + nil t)) + ;; Handlers such as "gio open" and kde-open5 start viewer in background + ;; and exit immediately. Avoid `start-process' since it assumes + ;; :connection-type `pty' and kills children processes with SIGHUP + ;; when temporary terminal session is finished (Bug#44824). + ;; An alternative is `process-connection-type' let-bound to nil for + ;; `start-process-shell-command' call (with no chance to report failure). + (make-process + :name "mailcap-view-file" + :connection-type 'pipe + :buffer nil ; "*Messages*" may be suitable for debugging + :sentinel (lambda (proc event) + (when (and (memq (process-status proc) '(exit signal)) + (/= (process-exit-status proc) 0)) + (message + "Command %s: %s." + (mapconcat #'identity (process-command proc) " ") + (substring event 0 -1)))) + :command (list shell-file-name shell-command-switch command))))) (provide 'mailcap) -- cgit v1.2.1 From 015d881b6dbdd527e309d8337daaf22d192a3c70 Mon Sep 17 00:00:00 2001 From: Lars Ingebrigtsen Date: Sat, 15 Jan 2022 11:55:18 +0100 Subject: Add emoji-alternate-names variable * lisp/international/emoji.el (emoji-alternate-names): New variable (bug#52860). (emoji-search): Note usage. (emoji--choose-emoji): Use it. --- lisp/international/emoji.el | 75 ++++++++++++++++++++++++++++++--------------- 1 file changed, 51 insertions(+), 24 deletions(-) diff --git a/lisp/international/emoji.el b/lisp/international/emoji.el index 264a1f09dc2..df488708afa 100644 --- a/lisp/international/emoji.el +++ b/lisp/international/emoji.el @@ -55,6 +55,14 @@ "Face for emojis that have derivations." :version "29.1") +(defvar emoji-alternate-names nil + "Alist of emojis and lists of alternate names for the emojis. +Each element in the alist should have the emoji (as a string) as +the first element, and the rest of the elements should be strings +representing names. For instance: + + (\"🤗\" \"hug\" \"hugging\" \"kind\")") + (defvar emoji--labels nil) (defvar emoji--all-bases nil) (defvar emoji--derived nil) @@ -90,8 +98,9 @@ of selecting from emoji display." ;;;###autoload (defun emoji-search () "Choose and insert an emoji glyph by typing its Unicode name. -This command prompts for an emoji name, with completion, and inserts it. -It recognizes the Unicode Standard names of emoji." +This command prompts for an emoji name, with completion, and +inserts it. It recognizes the Unicode Standard names of emoji, +and also consults the `emoji-alternate-names' alist." (interactive "*") (emoji--init) (emoji--choose-emoji)) @@ -647,29 +656,47 @@ We prefer the earliest unique letter." (defun emoji--choose-emoji () ;; Use the list of names. - (let ((name - (completing-read - "Insert emoji: " - (lambda (string pred action) - (if (eq action 'metadata) - (list 'metadata - (cons - 'affixation-function - ;; Add the glyphs to the start of the displayed - ;; strings when TAB-ing. - (lambda (strings) - (mapcar - (lambda (name) - (list name - (concat - (or (gethash name emoji--all-bases) " ") - "\t") - "")) - strings)))) - (complete-with-action action emoji--all-bases string pred))) - nil t))) + (let* ((table + (if (not emoji-alternate-names) + ;; If we don't have alternate names, do the efficient version. + emoji--all-bases + ;; Compute all the (possibly non-unique) names. + (let ((table nil)) + (maphash + (lambda (name glyph) + (push (concat name "\t" glyph) table)) + emoji--all-bases) + (dolist (elem emoji-alternate-names) + (dolist (name (cdr elem)) + (push (concat name "\t" (car elem)) table))) + (sort table #'string<)))) + (name + (completing-read + "Insert emoji: " + (lambda (string pred action) + (if (eq action 'metadata) + (list 'metadata + (cons + 'affixation-function + ;; Add the glyphs to the start of the displayed + ;; strings when TAB-ing. + (lambda (strings) + (mapcar + (lambda (name) + (if emoji-alternate-names + (list name "" "") + (list name + (concat + (or (gethash name emoji--all-bases) " ") + "\t") + ""))) + strings)))) + (complete-with-action action table string pred))) + nil t))) (when (cl-plusp (length name)) - (let* ((glyph (gethash name emoji--all-bases)) + (let* ((glyph (if emoji-alternate-names + (cadr (split-string name "\t")) + (gethash name emoji--all-bases))) (derived (gethash glyph emoji--derived))) (if (not derived) ;; Simple glyph with no derivations. -- cgit v1.2.1 From 7f36aca99dc1387cfeb599c9f2bb781036f79cf1 Mon Sep 17 00:00:00 2001 From: Philipp Stephani Date: Fri, 14 Jan 2022 20:49:35 +0100 Subject: * lisp/indent.el (tab-first-completion): Fix incorrect choices. --- lisp/indent.el | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lisp/indent.el b/lisp/indent.el index f0c11ad0df4..48e5b309e48 100644 --- a/lisp/indent.el +++ b/lisp/indent.el @@ -77,10 +77,11 @@ This variable has no effect unless `tab-always-indent' is `complete'." :group 'indent :type '(choice (const :tag "Always complete" nil) - (const :tag "Unless at the end of a line" 'eol) - (const :tag "Unless looking at a word" 'word) - (const :tag "Unless at a word or parenthesis" 'word-or-paren) - (const :tag "Unless at a word, parenthesis, or punctuation." 'word-or-paren-or-punct)) + (const :tag "Unless at the end of a line" eol) + (const :tag "Unless looking at a word" word) + (const :tag "Unless at a word or parenthesis" word-or-paren) + (const :tag "Unless at a word, parenthesis, or punctuation." + word-or-paren-or-punct)) :version "28.1") (defvar indent-line-ignored-functions '(indent-relative -- cgit v1.2.1 From 2dcb1bc47485791177917bfbd8fba95d69454135 Mon Sep 17 00:00:00 2001 From: Philipp Stephani Date: Sat, 15 Jan 2022 12:40:09 +0100 Subject: Mark a few more map tests as unstable on Emacs 28 (Bug#46722). At least for me, these tests still occasionally fail. Do not merge to master. * test/lisp/emacs-lisp/map-tests.el (test-map-into-hash-test) (test-map-merge, test-map-merge-with, test-map-merge-empty): Mark as unstable. --- test/lisp/emacs-lisp/map-tests.el | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/lisp/emacs-lisp/map-tests.el b/test/lisp/emacs-lisp/map-tests.el index 31be0784ecb..4fca8b36199 100644 --- a/test/lisp/emacs-lisp/map-tests.el +++ b/test/lisp/emacs-lisp/map-tests.el @@ -443,6 +443,9 @@ Evaluate BODY for each created map." (ert-deftest test-map-into-hash-test () "Test `map-into' with different hash-table test functions." + ;; This test is unstable in Emacs 28, but the problem has been fixed + ;; in Emacs 29 (bug#46722). + :tags '(:unstable) (should (eq (hash-table-test (map-into () 'hash-table)) #'equal)) (should (eq (hash-table-test (map-into () '(hash-table))) #'eql)) (should (eq (hash-table-test (map-into () '(hash-table :test eq))) #'eq)) @@ -473,6 +476,9 @@ Evaluate BODY for each created map." (ert-deftest test-map-merge () "Test `map-merge'." + ;; This test is unstable in Emacs 28, but the problem has been fixed + ;; in Emacs 29 (bug#46722). + :tags '(:unstable) (should (equal (sort (map-merge 'list '(a 1) '((b . 2) (c . 3)) #s(hash-table data (c 4))) (lambda (x y) (string< (car x) (car y)))) @@ -482,6 +488,9 @@ Evaluate BODY for each created map." (should (equal (map-merge 'plist () '(:a 1)) '(:a 1)))) (ert-deftest test-map-merge-with () + ;; This test is unstable in Emacs 28, but the problem has been fixed + ;; in Emacs 29 (bug#46722). + :tags '(:unstable) (should (equal (sort (map-merge-with 'list #'+ '((1 . 2)) '((1 . 3) (2 . 4)) @@ -494,6 +503,9 @@ Evaluate BODY for each created map." (ert-deftest test-map-merge-empty () "Test merging of empty maps." + ;; This test is unstable in Emacs 28, but the problem has been fixed + ;; in Emacs 29 (bug#46722). + :tags '(:unstable) (should-not (map-merge 'list)) (should-not (map-merge 'alist)) (should-not (map-merge 'plist)) -- cgit v1.2.1 From ae65f2089cfe108d761f8150280de520dba51b28 Mon Sep 17 00:00:00 2001 From: Po Lu Date: Sat, 15 Jan 2022 20:14:31 +0800 Subject: Use preferred XIM style without trying to detect if it's supported The old code would in general fall back to the default if the preferred style wasn't available, which is usually worse than what the user specified * src/xfns.c (best_xim_style): Stop checking if the preferred input style is supported. --- src/xfns.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/xfns.c b/src/xfns.c index ffad0bc3d1a..d73e951754b 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -2643,11 +2643,7 @@ best_xim_style (struct x_display_info *dpyinfo, int nr_supported = ARRAYELTS (supported_xim_styles); if (dpyinfo->preferred_xim_style) - { - for (j = 0; j < xim->count_styles; ++j) - if (dpyinfo->preferred_xim_style == xim->supported_styles[j]) - return dpyinfo->preferred_xim_style; - } + return dpyinfo->preferred_xim_style; for (i = 0; i < nr_supported; ++i) for (j = 0; j < xim->count_styles; ++j) -- cgit v1.2.1 From 17231a26d8ca754dab4eaf54c93f179f3465fd0c Mon Sep 17 00:00:00 2001 From: Lars Ingebrigtsen Date: Sat, 15 Jan 2022 14:15:54 +0100 Subject: Don't strip properties in show-paren-function * lisp/paren.el (show-paren-function): Don't strip text properties (bug#51606) because that makes the offscreen context less informative. --- lisp/paren.el | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lisp/paren.el b/lisp/paren.el index a1f74f2097e..0065bba72e7 100644 --- a/lisp/paren.el +++ b/lisp/paren.el @@ -330,9 +330,7 @@ It is the default value of `show-paren-data-function'." (let ((open-paren-line-string (blink-paren-open-paren-line-string openparen)) (message-log-max nil)) - (minibuffer-message - "Matches %s" - (substring-no-properties open-paren-line-string))))) + (minibuffer-message "Matches %s" open-paren-line-string)))) ;; Always set the overlay face, since it varies. (overlay-put show-paren--overlay 'priority show-paren-priority) (overlay-put show-paren--overlay 'face face)))))) -- cgit v1.2.1 From de3a95726540ffb4a3d2197f5581b684b8c3608f Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 15 Jan 2022 15:58:21 +0200 Subject: Fix setting cursor in pixel-scrolling modes * src/xdisp.c (redisplay_window): Don't set cursor to any glyph row past the one that contains EOB. (Bug#53275) --- src/xdisp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/xdisp.c b/src/xdisp.c index 977d31703fb..c695e466e78 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -19157,7 +19157,8 @@ redisplay_window (Lisp_Object window, bool just_this_one_p) struct glyph_row *row; row = MATRIX_FIRST_TEXT_ROW (w->desired_matrix); - while (MATRIX_ROW_BOTTOM_Y (row) < new_vpos) + while (MATRIX_ROW_BOTTOM_Y (row) < new_vpos + && !row->ends_at_zv_p) ++row; TEMP_SET_PT_BOTH (MATRIX_ROW_START_CHARPOS (row), -- cgit v1.2.1 From 525dc6e5c428185b62c72d7958cd4fe17937f126 Mon Sep 17 00:00:00 2001 From: Stefan Monnier Date: Sat, 15 Jan 2022 09:31:55 -0500 Subject: * pcvs-info.el (cvs-mode-toggle-mark): Typo --- lisp/vc/pcvs-info.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lisp/vc/pcvs-info.el b/lisp/vc/pcvs-info.el index f5520e19ce6..b48a4a1cbf1 100644 --- a/lisp/vc/pcvs-info.el +++ b/lisp/vc/pcvs-info.el @@ -130,7 +130,7 @@ to confuse some users sometimes." (defvar cvs-bakprefix ".#" "The prefix that CVS prepends to files when rcsmerge'ing.") -(declare-function 'cvs-mode-toggle-mark "pcvs" (e)) +(declare-function cvs-mode-toggle-mark "pcvs" (e)) (defvar-keymap cvs-status-map :doc "Local keymap for text properties of status." -- cgit v1.2.1 From 7055104358ad51b8c49e120851ee5d4d3c909e6d Mon Sep 17 00:00:00 2001 From: Juri Linkov Date: Sat, 15 Jan 2022 20:27:15 +0200 Subject: * doc/emacs/search.texi (Special Isearch): Move isearch-char-by-name item back Put it at the end of the list and still closer to isearch-emoji-by-name. --- doc/emacs/search.texi | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/emacs/search.texi b/doc/emacs/search.texi index fa1b0eee7c3..a57cfac8daf 100644 --- a/doc/emacs/search.texi +++ b/doc/emacs/search.texi @@ -463,14 +463,15 @@ transient input method (@pxref{transient input method}) with @kbd{C-x \} (@code{isearch-transient-input-method}) to insert a single character to the search string using an input method, and automatically disable the input method afterwards. -@end itemize +@item @findex isearch-char-by-name @kindex C-x 8 RET @r{(Incremental Search)} Type @kbd{C-x 8 @key{RET}} (@code{isearch-char-by-name}), followed by a Unicode name or code-point in hex. This adds the specified character into the search string, similar to the usual @code{insert-char} command (@pxref{Inserting Text}). +@end itemize @findex isearch-emoji-by-name @kindex C-x 8 e RET @r{(Incremental Search)} -- cgit v1.2.1 From f19b34376a2fe9f6f06226fb9cb0cb92119dbdca Mon Sep 17 00:00:00 2001 From: Juri Linkov Date: Sat, 15 Jan 2022 20:33:45 +0200 Subject: More fixes for recently committed context-menu additions from bug#52973 * lisp/hi-lock.el (highlight-symbol-at-mouse): New defalias. (hi-lock-face-symbol-at-mouse): Rename from hi-lock-symbol-at-mouse. (hi-lock-context-menu): Use thing-at-mouse and middle-separator. * lisp/man.el (Man-context-menu): Fix Man-at-mouse and use middle-separator. * lisp/mouse.el (context-menu-functions): Remove context-menu-online-search. Add occur-context-menu and dictionary-context-menu (bug#50552). --- lisp/hi-lock.el | 17 +++++++++-------- lisp/man.el | 10 ++++++---- lisp/mouse.el | 5 +++-- 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/lisp/hi-lock.el b/lisp/hi-lock.el index b70d4a75690..b77f9181a9c 100644 --- a/lisp/hi-lock.el +++ b/lisp/hi-lock.el @@ -855,7 +855,8 @@ SPACES-REGEXP is a regexp to substitute spaces in font-lock search." nil) ;;; Mouse support -(defun hi-lock-symbol-at-mouse (event) +(defalias 'highlight-symbol-at-mouse 'hi-lock-face-symbol-at-mouse) +(defun hi-lock-face-symbol-at-mouse (event) "Highlight symbol at mouse click EVENT." (interactive "e") (save-excursion @@ -865,13 +866,13 @@ SPACES-REGEXP is a regexp to substitute spaces in font-lock search." ;;;###autoload (defun hi-lock-context-menu (menu click) "Populate MENU with a menu item to highlight symbol at CLICK." - (save-excursion - (mouse-set-point click) - (when (symbol-at-point) - (define-key-after menu [highlight-search-separator] menu-bar-separator) - (define-key-after menu [highlight-search-mouse] - '(menu-item "Highlight Symbol" highlight-symbol-at-mouse - :help "Highlight symbol at point")))) + (when (thing-at-mouse click 'symbol) + (define-key-after menu [highlight-search-separator] menu-bar-separator + 'middle-separator) + (define-key-after menu [highlight-search-mouse] + '(menu-item "Highlight Symbol" highlight-symbol-at-mouse + :help "Highlight symbol at point") + 'highlight-search-separator)) menu) (provide 'hi-lock) diff --git a/lisp/man.el b/lisp/man.el index d6146a2c4dc..a53a696c313 100644 --- a/lisp/man.el +++ b/lisp/man.el @@ -1993,11 +1993,13 @@ Uses `Man-name-local-regexp'." (skip-syntax-backward "^ ") (and (looking-at "[[:space:]]*\\([[:alnum:]_-]+([[:alnum:]]+)\\)") - (match-string 1))) - (define-key-after menu [man-separator] menu-bar-separator) + (match-string 1))) + (define-key-after menu [man-separator] menu-bar-separator + 'middle-separator) (define-key-after menu [man-at-mouse] - '(menu-item "Open man page" man-at-mouse - :help "Open man page around mouse click")))) + '(menu-item "Open man page" Man-at-mouse + :help "Open man page around mouse click") + 'man-separator))) menu) diff --git a/lisp/mouse.el b/lisp/mouse.el index ad69d54fce4..82424e3e244 100644 --- a/lisp/mouse.el +++ b/lisp/mouse.el @@ -298,9 +298,10 @@ and should return the same menu with changes such as added new menu items." (function-item context-menu-buffers) (function-item context-menu-vc) (function-item context-menu-ffap) - (function-item Man-context-menu) (function-item hi-lock-context-menu) - (function-item context-menu-online-search) + (function-item occur-context-menu) + (function-item Man-context-menu) + (function-item dictionary-context-menu) (function :tag "Custom function"))) :version "28.1") -- cgit v1.2.1 From 791694c5fe86b8c9ab5cb593bd5e050aa185aa3a Mon Sep 17 00:00:00 2001 From: Juri Linkov Date: Sat, 15 Jan 2022 20:37:15 +0200 Subject: * lisp/mouse.el (context-menu-map): Select clicked window (bug#53249). --- lisp/mouse.el | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lisp/mouse.el b/lisp/mouse.el index 82424e3e244..502683d3d1e 100644 --- a/lisp/mouse.el +++ b/lisp/mouse.el @@ -324,6 +324,8 @@ the function `context-menu-filter-function'." (fun (mouse-posn-property (event-start click) 'context-menu-function))) + (select-window (posn-window (event-start click))) + (if (functionp fun) (setq menu (funcall fun menu click)) (run-hook-wrapped 'context-menu-functions -- cgit v1.2.1 From 95640360f09930e903575870e37e501dc67990ad Mon Sep 17 00:00:00 2001 From: Juri Linkov Date: Sat, 15 Jan 2022 20:58:31 +0200 Subject: * lisp/net/dictionary.el (dictionary-context-menu): Use package prefix. --- lisp/net/dictionary.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lisp/net/dictionary.el b/lisp/net/dictionary.el index 507363cc0f8..e0824f39716 100644 --- a/lisp/net/dictionary.el +++ b/lisp/net/dictionary.el @@ -1376,7 +1376,7 @@ any buffer where (dictionary-tooltip-mode 1) has been called." (dictionary-search word))) ;;;###autoload -(defun context-menu-dictionary (menu click) +(defun dictionary-context-menu (menu click) "Populate MENU with dictionary commands at CLICK. When you add this function to `context-menu-functions', the context menu will contain an item that searches -- cgit v1.2.1 From e488601849627c53b1638fbab1d115518e0ee794 Mon Sep 17 00:00:00 2001 From: Kyle Meyer Date: Sat, 15 Jan 2022 16:02:26 -0500 Subject: Update to Org 9.5.2-9-g7ba24c --- lisp/org/ob-gnuplot.el | 25 ++++++++++--------------- lisp/org/org-agenda.el | 5 ++++- lisp/org/org-version.el | 2 +- lisp/org/org.el | 20 +++++++++++--------- lisp/org/ox-ascii.el | 6 +++++- 5 files changed, 31 insertions(+), 27 deletions(-) diff --git a/lisp/org/ob-gnuplot.el b/lisp/org/ob-gnuplot.el index 69a5f5f91bd..895738822de 100644 --- a/lisp/org/ob-gnuplot.el +++ b/lisp/org/ob-gnuplot.el @@ -129,6 +129,7 @@ code." (title (cdr (assq :title params))) (lines (cdr (assq :line params))) (sets (cdr (assq :set params))) + (missing (cdr (assq :missing params))) (x-labels (cdr (assq :xlabels params))) (y-labels (cdr (assq :ylabels params))) (timefmt (cdr (assq :timefmt params))) @@ -138,6 +139,7 @@ code." (file-name-directory (buffer-file-name)))) (add-to-body (lambda (text) (setq body (concat text "\n" body))))) ;; append header argument settings to body + (when missing (funcall add-to-body (format "set datafile missing '%s'" missing))) (when title (funcall add-to-body (format "set title '%s'" title))) (when lines (mapc (lambda (el) (funcall add-to-body el)) lines)) (when sets @@ -288,21 +290,14 @@ Pass PARAMS through to `orgtbl-to-generic' when exporting TABLE." (with-temp-file data-file (insert (let ((org-babel-gnuplot-timestamp-fmt (or (plist-get params :timefmt) "%Y-%m-%d-%H:%M:%S"))) - (replace-regexp-in-string - ;; org export backend adds "|" at the beginning/end of - ;; the table lines. Strip those. - "^|\\(.+\\)|$" - "\\1" - (orgtbl-to-generic - table - (org-combine-plists - '( :sep "\t" :fmt org-babel-gnuplot-quote-tsv-field - ;; Two setting below are needed to make :fmt work. - :raw t - ;; Use `org', not `ascii' because `ascii' may - ;; sometimes mishandle quoted strings. - :backend org) - params)))))) + (orgtbl-to-generic + table + (org-combine-plists + '( :sep "\t" :fmt org-babel-gnuplot-quote-tsv-field + ;; Two setting below are needed to make :fmt work. + :raw t + :backend ascii) + params))))) data-file) (provide 'ob-gnuplot) diff --git a/lisp/org/org-agenda.el b/lisp/org/org-agenda.el index fed36ac9b63..94aea1b0a32 100644 --- a/lisp/org/org-agenda.el +++ b/lisp/org/org-agenda.el @@ -86,6 +86,8 @@ (declare-function org-capture "org-capture" (&optional goto keys)) (declare-function org-clock-modify-effort-estimate "org-clock" (&optional value)) +(declare-function org-element-type "org-element" (&optional element)) + (defvar calendar-mode-map) (defvar org-clock-current-task) (defvar org-current-tag-alist) @@ -5729,7 +5731,8 @@ displayed in agenda view." (org-at-planning-p) (org-before-first-heading-p) (and org-agenda-include-inactive-timestamps - (org-at-clock-log-p))) + (org-at-clock-log-p)) + (not (eq 'timestamp (org-element-type (org-element-context))))) (throw :skip nil)) (org-agenda-skip)) (let* ((pos (match-beginning 0)) diff --git a/lisp/org/org-version.el b/lisp/org/org-version.el index 1053bbe22cc..5337d9df746 100644 --- a/lisp/org/org-version.el +++ b/lisp/org/org-version.el @@ -11,7 +11,7 @@ Inserted by installing Org mode or when a release is made." (defun org-git-version () "The Git version of Org mode. Inserted by installing Org or when a release is made." - (let ((org-git-version "release_9.5.2-3-geb9f34")) + (let ((org-git-version "release_9.5.2-9-g7ba24c")) org-git-version)) (provide 'org-version) diff --git a/lisp/org/org.el b/lisp/org/org.el index 8c09a057cc7..7ea8d65f3b9 100644 --- a/lisp/org/org.el +++ b/lisp/org/org.el @@ -18731,17 +18731,19 @@ With prefix arg UNCOMPILED, load the uncompiled versions." "Is S an ID created by UUIDGEN?" (string-match "\\`[0-9a-f]\\{8\\}-[0-9a-f]\\{4\\}-[0-9a-f]\\{4\\}-[0-9a-f]\\{4\\}-[0-9a-f]\\{12\\}\\'" (downcase s))) -(defun org-in-src-block-p (&optional inside) +(defun org-in-src-block-p (&optional inside element) "Whether point is in a code source block. When INSIDE is non-nil, don't consider we are within a source -block when point is at #+BEGIN_SRC or #+END_SRC." - (let ((case-fold-search t)) - (or (and (eq (get-char-property (point) 'src-block) t)) - (and (not inside) - (save-match-data - (save-excursion - (beginning-of-line) - (looking-at ".*#\\+\\(begin\\|end\\)_src"))))))) +block when point is at #+BEGIN_SRC or #+END_SRC. +When ELEMENT is provided, it is considered to be element at point." + (save-match-data (setq element (or element (org-element-at-point)))) + (when (eq 'src-block (org-element-type element)) + (or (not inside) + (not (or (= (line-beginning-position) + (org-element-property :post-affiliated element)) + (= (1+ (line-end-position)) + (- (org-element-property :end element) + (org-element-property :post-blank element)))))))) (defun org-context () "Return a list of contexts of the current cursor position. diff --git a/lisp/org/ox-ascii.el b/lisp/org/ox-ascii.el index c22bb13b6dd..38b2a5772c1 100644 --- a/lisp/org/ox-ascii.el +++ b/lisp/org/ox-ascii.el @@ -1929,7 +1929,11 @@ a communication channel." (org-export-table-cell-alignment table-cell info))))) (setq contents (concat data - (make-string (- width (string-width (or data ""))) ?\s)))) + ;; FIXME: If CONTENTS was transformed by filters, + ;; the whole width calculation can be wrong. + ;; At least, make sure that we do not throw error + ;; when CONTENTS is larger than width. + (make-string (max 0 (- width (string-width (or data "")))) ?\s)))) ;; Return cell. (concat (format " %s " contents) (when (memq 'right (org-export-table-cell-borders table-cell info)) -- cgit v1.2.1 From 77d823794eacd73469d32fe780b7dd4eae213b34 Mon Sep 17 00:00:00 2001 From: Tassilo Horn Date: Sat, 15 Jan 2022 23:59:20 +0100 Subject: Add some more mailcap tests. * test/lisp/net/mailcap-resources/mailcap: New file. * test/lisp/net/mailcap-resources/test.test: New file. * test/lisp/net/mailcap-tests.el (with-pristine-mailcap): New macro. (mailcap-parsing-and-mailcap-mime-info): New test for parsing mailcap files and selecting the right viewer. (mailcap--test-result): New variable. (mailcap--test-viewer): New function. (mailcap-view-file): New test for mailcap-view-file. --- test/lisp/net/mailcap-resources/mailcap | 9 ++++ test/lisp/net/mailcap-resources/test.test | 1 + test/lisp/net/mailcap-tests.el | 70 +++++++++++++++++++++++++++++++ 3 files changed, 80 insertions(+) create mode 100644 test/lisp/net/mailcap-resources/mailcap create mode 100644 test/lisp/net/mailcap-resources/test.test diff --git a/test/lisp/net/mailcap-resources/mailcap b/test/lisp/net/mailcap-resources/mailcap new file mode 100644 index 00000000000..ad3f7404fda --- /dev/null +++ b/test/lisp/net/mailcap-resources/mailcap @@ -0,0 +1,9 @@ +audio/ogg; mpv %s +audio/flac; mpv %s +audio/x-wav; aplay %s +text/*; emacsclient -t %s +application/pdf; acroread %s; test=false +application/pdf; evince %s +application/pdf; okular %s +image/*; eog %s +image/svg+xml; inkscape %s diff --git a/test/lisp/net/mailcap-resources/test.test b/test/lisp/net/mailcap-resources/test.test new file mode 100644 index 00000000000..9daeafb9864 --- /dev/null +++ b/test/lisp/net/mailcap-resources/test.test @@ -0,0 +1 @@ +test diff --git a/test/lisp/net/mailcap-tests.el b/test/lisp/net/mailcap-tests.el index 362cb22bb2f..b439c08c791 100644 --- a/test/lisp/net/mailcap-tests.el +++ b/test/lisp/net/mailcap-tests.el @@ -63,4 +63,74 @@ (append mailcap-tests-path-extensions mailcap-tests-mime-extensions)))) +(defmacro with-pristine-mailcap (&rest body) + ;; We only want the mailcap info we define ourselves. + `(let (mailcap--computed-mime-data + mailcap-mime-data + mailcap-user-mime-data) + ;; `mailcap-mime-info' calls `mailcap-parse-mailcaps' which parses + ;; the system's mailcaps. We don't want that for our test. + (cl-letf (((symbol-function 'mailcap-parse-mailcaps) #'ignore)) + ,@body))) + +(ert-deftest mailcap-parsing-and-mailcap-mime-info () + (with-pristine-mailcap + ;; One mailcap entry has a test=false field. The shell command + ;; execution errors when running the tests from the Makefile + ;; because then HOME=/nonexistent. + (ert-with-temp-directory home + (setenv "HOME" home) + ;; Now parse our resource mailcap file. + (mailcap-parse-mailcap (ert-resource-file "mailcap")) + + ;; Assert that we get what we have defined. + (dolist (type '("audio/ogg" "audio/flac")) + (should (string= "mpv %s" (mailcap-mime-info type)))) + (should (string= "aplay %s" (mailcap-mime-info "audio/x-wav"))) + (should (string= "emacsclient -t %s" + (mailcap-mime-info "text/plain"))) + ;; evince is chosen because acroread has test=false and okular + ;; comes later. + (should (string= "evince %s" + (mailcap-mime-info "application/pdf"))) + (should (string= "inkscape %s" + (mailcap-mime-info "image/svg+xml"))) + (should (string= "eog %s" + (mailcap-mime-info "image/jpg"))) + ;; With REQUEST being a number, all fields of the selected entry + ;; should be returned. + (should (equal '((viewer . "evince %s") + (type . "application/pdf")) + (mailcap-mime-info "application/pdf" 1))) + ;; With 'all, all applicable entries should be returned. + (should (equal '(((viewer . "evince %s") + (type . "application/pdf")) + ((viewer . "okular %s") + (type . "application/pdf"))) + (mailcap-mime-info "application/pdf" 'all))) + (let* ((c nil) + (toggle (lambda (_) (setq c (not c))))) + (mailcap-add "audio/ogg" "toggle %s" toggle) + (should (string= "toggle %s" (mailcap-mime-info "audio/ogg"))) + ;; The test results are cached, so in order to have the test + ;; re-evaluated, one needs to clear the cache. + (setq mailcap-viewer-test-cache nil) + (should (string= "mpv %s" (mailcap-mime-info "audio/ogg"))) + (setq mailcap-viewer-test-cache nil) + (should (string= "toggle %s" (mailcap-mime-info "audio/ogg"))))))) + +(defvar mailcap--test-result nil) +(defun mailcap--test-viewer () + (setq mailcap--test-result (string= (buffer-string) "test\n"))) + +(ert-deftest mailcap-view-file () + (with-pristine-mailcap + ;; Try using a lambda as viewer and check wether + ;; `mailcap-view-file' works correctly. + (let* ((mailcap-mime-extensions '((".test" . "test/test")))) + (mailcap-add "test/test" 'mailcap--test-viewer) + (save-window-excursion + (mailcap-view-file (ert-resource-file "test.test"))) + (should mailcap--test-result)))) + ;;; mailcap-tests.el ends here -- cgit v1.2.1 From 80c52346c287ddc5e15663c25a1fea18d2ee4fad Mon Sep 17 00:00:00 2001 From: Po Lu Date: Sun, 16 Jan 2022 00:47:41 +0000 Subject: Fix a minor snafu when resizing frames on Haiku * src/haiku_support.cc (BWindow_resize): Adjust for minor snafu where BWindow::ResizeTo uses BRect-style width and height instead of actual width and height. --- src/haiku_support.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/haiku_support.cc b/src/haiku_support.cc index d49e319b98c..4b180f98b7c 100644 --- a/src/haiku_support.cc +++ b/src/haiku_support.cc @@ -1861,7 +1861,7 @@ BWindow_retitle (void *window, const char *title) void BWindow_resize (void *window, int width, int height) { - ((BWindow *) window)->ResizeTo (width, height); + ((BWindow *) window)->ResizeTo (width - 1, height - 1); } /* Activate WINDOW, making it the subject of keyboard focus and -- cgit v1.2.1 From c59e870cceb2f40040d6c02da7658c58054ab3ad Mon Sep 17 00:00:00 2001 From: Po Lu Date: Sun, 16 Jan 2022 10:05:17 +0800 Subject: * src/xwidget.c (webkit_js_to_lisp): Use correct constant to check size. --- src/xwidget.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/xwidget.c b/src/xwidget.c index 45879b15cbe..fce0aafb099 100644 --- a/src/xwidget.c +++ b/src/xwidget.c @@ -1855,7 +1855,7 @@ webkit_js_to_lisp (JSCValue *value) const gint32 dlen = jsc_value_to_int32 (len); Lisp_Object obj; - if (! (0 <= dlen && dlen < PTRDIFF_MAX + 1.0)) + if (! (0 <= dlen && dlen < G_MAXINT32 + 1)) memory_full (SIZE_MAX); ptrdiff_t n = dlen; -- cgit v1.2.1 From e2b9f3347e7f30e7185c5d07bc722ea0178f4dbe Mon Sep 17 00:00:00 2001 From: Po Lu Date: Sun, 16 Jan 2022 13:46:39 +0800 Subject: Update modifier meanings even if an xkb_desc was not available * src/xterm.c (handle_one_event): Always update modifiers after the keyboard mapping is refreshed. --- src/xterm.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/xterm.c b/src/xterm.c index 5798ea3eebc..4b5358ed658 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -11526,8 +11526,6 @@ handle_one_xevent (struct x_display_info *dpyinfo, XkbFreeKeyboard (dpyinfo->xkb_desc, XkbAllComponentsMask, True); dpyinfo->xkb_desc = NULL; } - - x_find_modifier_meanings (dpyinfo); } else { @@ -11545,6 +11543,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, } XkbRefreshKeyboardMapping (&xkbevent->map); + x_find_modifier_meanings (dpyinfo); } } #endif -- cgit v1.2.1 From 9b308a333bcb5cc040cb09d0d676ed5d260f0920 Mon Sep 17 00:00:00 2001 From: Po Lu Date: Sun, 16 Jan 2022 05:57:14 +0000 Subject: Avoid focus and allow monospace text in tooltip frames on Haiku * src/haikufns.c (Fx_show_tip): Set avoid focus on tooltip frames. * src/haikuterm.c (haiku_default_font_parameter): Don't special case the default font on tooltip frames, since the bug that was supposed to work around has already been fixed. --- src/haikufns.c | 1 + src/haikuterm.c | 5 +---- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/haikufns.c b/src/haikufns.c index 52bb13bc89b..6a5fdf55485 100644 --- a/src/haikufns.c +++ b/src/haikufns.c @@ -2001,6 +2001,7 @@ DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0, BWindow_resize (FRAME_HAIKU_WINDOW (tip_f), width, height); haiku_set_offset (tip_f, root_x, root_y, 1); BWindow_set_tooltip_decoration (FRAME_HAIKU_WINDOW (tip_f)); + BWindow_set_avoid_focus (FRAME_HAIKU_WINDOW (tip_f), true); BView_set_view_cursor (FRAME_HAIKU_VIEW (tip_f), FRAME_OUTPUT_DATA (XFRAME (frame))->current_cursor); SET_FRAME_VISIBLE (tip_f, 1); diff --git a/src/haikuterm.c b/src/haikuterm.c index ad89985b748..7380420e531 100644 --- a/src/haikuterm.c +++ b/src/haikuterm.c @@ -2479,10 +2479,7 @@ haiku_default_font_parameter (struct frame *f, Lisp_Object parms) struct haiku_font_pattern ptn; ptn.specified = 0; - if (f->tooltip) - BFont_populate_plain_family (&ptn); - else - BFont_populate_fixed_family (&ptn); + BFont_populate_fixed_family (&ptn); if (ptn.specified & FSPEC_FAMILY) font = font_open_by_name (f, build_unibyte_string (ptn.family)); -- cgit v1.2.1 From da35e9d5efa0e3f5e5582c633dfc093847ed6fc0 Mon Sep 17 00:00:00 2001 From: Yuuki Harano Date: Sun, 16 Jan 2022 17:25:28 +0900 Subject: * src/pgtkterm.c (evq_flush): Shift events one by one --- src/pgtkterm.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 0155ae991d3..4c38ff5a597 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -153,10 +153,24 @@ static int evq_flush (struct input_event *hold_quit) { struct event_queue_t *evq = &event_q; - int i, n = evq->nr; - for (i = 0; i < n; i++) - kbd_buffer_store_buffered_event (&evq->q[i], hold_quit); - evq->nr = 0; + int n = 0; + + while (evq->nr > 0) + { + /* kbd_buffer_store_buffered_event may do longjmp, so + we need to shift event queue first and pass the event + to kbd_buffer_store_buffered_event so that events in + queue are not processed twice. Bug#52941 */ + union buffered_input_event ev = evq->q[0]; + int i; + for (i = 1; i < evq->nr; i++) + evq->q[i - 1] = evq->q[i]; + evq->nr--; + + kbd_buffer_store_buffered_event (&ev, hold_quit); + n++; + } + return n; } -- cgit v1.2.1 From 0ae6491a899bf1642a06cac545f9cb31b33f1645 Mon Sep 17 00:00:00 2001 From: Po Lu Date: Sun, 16 Jan 2022 18:02:04 +0800 Subject: * src/gtkutil.c (xg_widget_key_press_event_cb): Also raise input signal. --- src/gtkutil.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/gtkutil.c b/src/gtkutil.c index d17a6970b8d..48e981d0d9a 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -6256,6 +6256,9 @@ xg_widget_key_press_event_cb (GtkWidget *widget, GdkEvent *event, } XNoOp (FRAME_X_DISPLAY (f)); +#ifdef USABLE_SIGIO + raise (SIGIO); +#endif return true; } -- cgit v1.2.1 From df53beb2db4a3aeba24b43ac748538e7daf06f8c Mon Sep 17 00:00:00 2001 From: Po Lu Date: Sun, 16 Jan 2022 10:12:22 +0000 Subject: Reduce poll time for Haiku file dialogs * src/haiku_support.c (be_popup_file_dialog): Reduce idle processor load by increasing timeout. The timeout is still too low to be noticable by the user. --- src/haiku_support.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/haiku_support.cc b/src/haiku_support.cc index 4b180f98b7c..de2c798b651 100644 --- a/src/haiku_support.cc +++ b/src/haiku_support.cc @@ -2818,7 +2818,7 @@ be_popup_file_dialog (int open_p, const char *default_dir, int must_match_p, int enum haiku_event_type type; char *ptr = NULL; - if (!haiku_read_with_timeout (&type, buf, 200, 100000)) + if (!haiku_read_with_timeout (&type, buf, 200, 1000000)) { block_input_function (); if (type != FILE_PANEL_EVENT) -- cgit v1.2.1 From 7f074fecf4516031699f443f8a88f925a73d1147 Mon Sep 17 00:00:00 2001 From: Po Lu Date: Sun, 16 Jan 2022 10:43:22 +0000 Subject: Make help event generation on Haiku behave closer to X * src/haikuterm.c (haiku_read_socket): Generate help events more like how X does it. --- src/haikuterm.c | 38 ++++++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/src/haikuterm.c b/src/haikuterm.c index 7380420e531..05f9788f184 100644 --- a/src/haikuterm.c +++ b/src/haikuterm.c @@ -55,6 +55,8 @@ struct unhandled_event uint8_t buffer[200]; }; +static bool any_help_event_p = false; + char * get_keysym_name (int keysym) { @@ -2594,6 +2596,7 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit) struct unhandled_event *unhandled_events = NULL; int button_or_motion_p; int need_flush = 0; + int do_help = 0; if (!buf) buf = xmalloc (200); @@ -2774,8 +2777,9 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit) } haiku_new_focus_frame (x_display_list->focused_frame); - help_echo_string = Qnil; - gen_help_event (Qnil, frame, Qnil, Qnil, 0); + + if (any_help_event_p) + do_help = -1; } else { @@ -2820,9 +2824,9 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit) remember_mouse_glyph (f, b->x, b->y, &FRAME_DISPLAY_INFO (f)->last_mouse_glyph); dpyinfo->last_mouse_glyph_frame = f; - gen_help_event (help_echo_string, frame, help_echo_window, - help_echo_object, help_echo_pos); } + else + help_echo_string = previous_help_echo_string; if (!NILP (Vmouse_autoselect_window)) { @@ -2842,6 +2846,10 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit) last_mouse_window = window; } + + if (!NILP (help_echo_string) + || !NILP (previous_help_echo_string)) + do_help = 1; } break; } @@ -3293,6 +3301,28 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit) xfree (old); } + if (do_help && !(hold_quit && hold_quit->kind != NO_EVENT)) + { + Lisp_Object help_frame = Qnil; + + if (x_display_list->last_mouse_frame) + XSETFRAME (help_frame, + x_display_list->last_mouse_frame); + + if (do_help > 0) + { + any_help_event_p = true; + gen_help_event (help_echo_string, help_frame, + help_echo_window, help_echo_object, + help_echo_pos); + } + else + { + help_echo_string = Qnil; + gen_help_event (Qnil, help_frame, Qnil, Qnil, 0); + } + } + if (need_flush) flush_dirty_back_buffers (); -- cgit v1.2.1 From 5476026119cfe35a4ff7a19f2a828152f56e0b2d Mon Sep 17 00:00:00 2001 From: Po Lu Date: Sun, 16 Jan 2022 11:02:58 +0000 Subject: Use kMenuWindowFeel on Haiku toolkip windows * src/haiku_support.cc (BWindow_set_tooltip_decoration): Use kMenuWindowFeel and set flags here. * src/haikufns.c (Fx_show_tip): Don't set_avoid_focus manually since setting tooltip decorations already does that. --- src/haiku_support.cc | 6 +++++- src/haikufns.c | 1 - 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/haiku_support.cc b/src/haiku_support.cc index de2c798b651..22605335c55 100644 --- a/src/haiku_support.cc +++ b/src/haiku_support.cc @@ -2224,7 +2224,11 @@ BWindow_set_tooltip_decoration (void *window) if (!w->LockLooper ()) gui_abort ("Failed to lock window while setting ttip decoration"); w->SetLook (B_BORDERED_WINDOW_LOOK); - w->SetFeel (B_FLOATING_APP_WINDOW_FEEL); + w->SetFeel (kMenuWindowFeel); + w->SetFlags (B_NOT_ZOOMABLE + | B_NOT_MINIMIZABLE + | B_AVOID_FRONT + | B_AVOID_FOCUS); w->UnlockLooper (); } diff --git a/src/haikufns.c b/src/haikufns.c index 6a5fdf55485..52bb13bc89b 100644 --- a/src/haikufns.c +++ b/src/haikufns.c @@ -2001,7 +2001,6 @@ DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0, BWindow_resize (FRAME_HAIKU_WINDOW (tip_f), width, height); haiku_set_offset (tip_f, root_x, root_y, 1); BWindow_set_tooltip_decoration (FRAME_HAIKU_WINDOW (tip_f)); - BWindow_set_avoid_focus (FRAME_HAIKU_WINDOW (tip_f), true); BView_set_view_cursor (FRAME_HAIKU_VIEW (tip_f), FRAME_OUTPUT_DATA (XFRAME (frame))->current_cursor); SET_FRAME_VISIBLE (tip_f, 1); -- cgit v1.2.1 From 1220cf605b108751dae88e02aeadbef90bd83cc9 Mon Sep 17 00:00:00 2001 From: Po Lu Date: Sun, 16 Jan 2022 19:45:54 +0800 Subject: Fix the xft build * src/xsettings.h [!HAVE_PGTK]: Include dispextern.h and remove duplicate definition of Display_Info. --- src/xsettings.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/xsettings.h b/src/xsettings.h index 266526df101..ccaa36489d0 100644 --- a/src/xsettings.h +++ b/src/xsettings.h @@ -21,15 +21,14 @@ along with GNU Emacs. If not, see . */ #define XSETTINGS_H #ifndef HAVE_PGTK +#include "dispextern.h" #include #endif struct x_display_info; struct pgtk_display_info; -#ifndef HAVE_PGTK -typedef struct x_display_info Display_Info; -#else +#ifdef HAVE_PGTK typedef struct pgtk_display_info Display_Info; #endif -- cgit v1.2.1 From 8f652465238aff062851a1f8bf1d76f5503ac1a9 Mon Sep 17 00:00:00 2001 From: Po Lu Date: Sun, 16 Jan 2022 21:39:14 +0800 Subject: Fix XI2 event filtering for very old versions of libXi * src/xterm.c (handle_one_xevent): Handle cases where xev->display is NULL. --- src/xterm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/xterm.c b/src/xterm.c index 4b5358ed658..3328e659301 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -10711,7 +10711,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, if (f && xev->evtype == XI_ButtonPress && !popup_activated () - && !x_window_to_scroll_bar (xev->display, xev->event, 2) + && !x_window_to_scroll_bar (dpyinfo->display, xev->event, 2) && !FRAME_NO_ACCEPT_FOCUS (f)) { /* When clicking into a child frame or when clicking @@ -10884,7 +10884,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, xkey.type = KeyPress; xkey.serial = xev->serial; xkey.send_event = xev->send_event; - xkey.display = xev->display; + xkey.display = dpyinfo->display; xkey.window = xev->event; xkey.root = xev->root; xkey.subwindow = xev->child; @@ -11230,7 +11230,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, xkey.type = KeyRelease; xkey.serial = xev->serial; xkey.send_event = xev->send_event; - xkey.display = xev->display; + xkey.display = dpyinfo->display; xkey.window = xev->event; xkey.root = xev->root; xkey.subwindow = xev->child; -- cgit v1.2.1 From 5c30c8778dffb647528d2144e00a48eaf723416e Mon Sep 17 00:00:00 2001 From: Matthias Meulien Date: Sun, 16 Jan 2022 20:13:21 +0200 Subject: Extend Outline mode with default visibility state * etc/NEWS: Announce support for default visibility state (bug#51809). * lisp/outline.el (outline-mode, outline-minor-mode): Ensure default visibility state is applied with outline-apply-default-state. (outline-default-state, outline-default-rules) (outline-default-long-line, outline-default-line-count): New defcustoms. (outline-apply-default-state, outline-show-only-headings) (outline--show-headings-up-to-level): New functions. --- etc/NEWS | 10 ++++ lisp/outline.el | 178 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 186 insertions(+), 2 deletions(-) diff --git a/etc/NEWS b/etc/NEWS index ea9ba49892f..2e748ce7c5b 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -243,6 +243,16 @@ These will take you (respectively) to the next and previous "page". --- *** 'describe-char' now also outputs the name of emoji combinations. +** Outline Mode + +*** Support for a default visibility state. +Customize the option 'outline-default-state' to define what headings +are visible when the mode is set. When equal to a number, the option +'outline-default-rules' determines the visibility of the subtree +starting at the corresponding level. Values are provided to show +a heading subtree unless the heading match a regexp, or its subtree +has long lines or is long. + ** Outline Minor Mode +++ diff --git a/lisp/outline.el b/lisp/outline.el index 4027142c94e..8e4af64370b 100644 --- a/lisp/outline.el +++ b/lisp/outline.el @@ -351,7 +351,8 @@ Turning on outline mode calls the value of `text-mode-hook' and then of '(outline-font-lock-keywords t nil nil backward-paragraph)) (setq-local imenu-generic-expression (list (list nil (concat "^\\(?:" outline-regexp "\\).*$") 0))) - (add-hook 'change-major-mode-hook #'outline-show-all nil t)) + (add-hook 'change-major-mode-hook #'outline-show-all nil t) + (add-hook 'hack-local-variables-hook #'outline-apply-default-state nil t)) (defvar outline-minor-mode-map) @@ -434,7 +435,8 @@ See the command `outline-mode' for more information on this mode." nil t) (setq-local line-move-ignore-invisible t) ;; Cause use of ellipses for invisible text. - (add-to-invisibility-spec '(outline . t))) + (add-to-invisibility-spec '(outline . t)) + (outline-apply-default-state)) (when outline-minor-mode-highlight (if font-lock-fontified (font-lock-remove-keywords nil outline-font-lock-keywords)) @@ -1303,6 +1305,178 @@ convenient way to make a table of contents of the buffer." (insert "\n\n")))))) (kill-new (buffer-string))))))) +(defcustom outline-default-state nil + "If non-nil, some headings are initially outlined. + +Note that the default state is applied when the major mode is set +or when the command `outline-apply-default-state' is called +interactively. + +When nil, headings visibility is left unchanged. + +If equal to `outline-show-all', all text of buffer is shown. + +If equal to `outline-show-only-headings', only headings are shown. + +If equal to a number, show only headings up to and including the +corresponding level. See `outline-default-rules' to customize +visibility of the subtree at the choosen level. + +If equal to a lambda function or function name, this function is +expected to toggle headings visibility, and will be called after +the mode is enabled." + :version "29.1" + :type '(choice (const :tag "Disabled" nil) + (const :tag "Show all" outline-show-all) + (const :tag "Only headings" outline-show-only-headings) + (natnum :tag "Show headings up to level" :value 1) + (function :tag "Custom function"))) + +(defcustom outline-default-rules nil + "Determines visibility of subtree starting at `outline-default-state' level. + +When nil, the subtree is hidden unconditionally. + +When equal to a list, each element should be one of the following: + +- A cons cell with CAR `match-regexp' and CDR a regexp, the + subtree will be hidden when the outline heading match the + regexp. + +- `subtree-has-long-lines' to only show the heading branches when + long lines are detected in its subtree (see + `outline-default-long-line' for the definition of long lines). + +- `subtree-is-long' to only show the heading branches when its + subtree contains more than `outline-default-line-count' lines. + +- A lambda function or function name which will be evaluated with + point at the beginning of the heading and the match data set + appropriately, the function being expected to toggle the + heading visibility." + :version "29.1" + :type '(choice (const :tag "Hide subtree" nil) + (set :tag "Show subtree unless" + (cons :tag "Heading match regexp" + (const match-regexp) string) + (const :tag "Subtree has long lines" + subtree-has-long-lines) + (const :tag "Subtree is long" + subtree-is-long) + (cons :tag "Custom function" + (const custom-function) function)))) + +(defcustom outline-default-long-line 1000 + "Minimal number of characters in a line for a heading to be outlined." + :version "29.1" + :type '(natnum :tag "Number of characters")) + +(defcustom outline-default-line-count 50 + "Minimal number of lines for a heading to be outlined." + :version "29.1" + :type '(natnum :tag "Number of lines")) + +(defun outline-apply-default-state () + "Apply the outline state defined by `outline-default-state'." + (interactive) + (cond + ((integerp outline-default-state) + (outline--show-headings-up-to-level outline-default-state)) + ((functionp outline-default-state) + (funcall outline-default-state)))) + +(defun outline-show-only-headings () + "Show only headings." + (interactive) + (outline-show-all) + (outline-hide-region-body (point-min) (point-max))) + +(eval-when-compile (require 'so-long)) +(autoload 'so-long-detected-long-line-p "so-long") +(defvar so-long-skip-leading-comments) +(defvar so-long-threshold) +(defvar so-long-max-lines) + +(defun outline--show-headings-up-to-level (level) + "Show only headings up to a LEVEL level. + +Like `outline-hide-sublevels' but, for each heading at level +LEVEL, decides of subtree visibility according to +`outline-default-rules'." + (if (not outline-default-rules) + (outline-hide-sublevels level) + (if (< level 1) + (error "Must keep at least one level of headers")) + (save-excursion + (let* (outline-view-change-hook + (beg (progn + (goto-char (point-min)) + ;; Skip the prelude, if any. + (unless (outline-on-heading-p t) (outline-next-heading)) + (point))) + (end (progn + (goto-char (point-max)) + ;; Keep empty last line, if available. + (if (bolp) (1- (point)) (point)))) + (heading-regexp + (cdr-safe + (assoc 'match-regexp outline-default-rules))) + (check-line-count + (memq 'subtree-is-long outline-default-rules)) + (check-long-lines + (memq 'subtree-has-long-lines outline-default-rules)) + (custom-function + (cdr-safe + (assoc 'custom-function outline-default-rules)))) + (if (< end beg) + (setq beg (prog1 end (setq end beg)))) + ;; First hide everything. + (outline-hide-sublevels level) + ;; Then unhide the top level headers. + (outline-map-region + (lambda () + (let ((current-level (funcall outline-level))) + (when (< current-level level) + (outline-show-heading) + (outline-show-entry)) + (when (= current-level level) + (cond + ((and heading-regexp + (let ((beg (point)) + (end (progn (outline-end-of-heading) (point)))) + (string-match-p heading-regexp (buffer-substring beg end)))) + ;; hide entry when heading match regexp + (outline-hide-entry)) + ((and check-line-count + (save-excursion + (let ((beg (point)) + (end (progn (outline-end-of-subtree) (point)))) + (<= outline-default-line-count (count-lines beg end))))) + ;; show only branches when line count of subtree > + ;; threshold + (outline-show-branches)) + ((and check-long-lines + (save-excursion + (let ((beg (point)) + (end (progn (outline-end-of-subtree) (point)))) + (save-restriction + (narrow-to-region beg end) + (let ((so-long-skip-leading-comments nil) + (so-long-threshold outline-default-long-line) + (so-long-max-lines nil)) + (so-long-detected-long-line-p)))))) + ;; show only branches when long lines are detected + ;; in subtree + (outline-show-branches)) + (custom-function + ;; call custom function if defined + (funcall custom-function)) + (t + ;; if no previous clause succeeds, show subtree + (outline-show-subtree)))))) + beg end))) + (run-hooks 'outline-view-change-hook))) + (defun outline--cycle-state () "Return the cycle state of current heading. Return either 'hide-all, 'headings-only, or 'show-all." -- cgit v1.2.1 From 714e11d53534416b6519396a9df5d62054731810 Mon Sep 17 00:00:00 2001 From: Juri Linkov Date: Sun, 16 Jan 2022 22:58:30 +0200 Subject: Add undelete-frame-max instead of undelete-frame-mode (bug#51883) * doc/emacs/frames.texi (Frame Commands): Replace undelete-frame-mode with undelete-frame-max. * lisp/frame.el (undelete-frame-max): New defcustom, by default 1. (undelete-frame--handle-delete-frame): Use undelete-frame-max instead of hard-coded 16. (undelete-frame-mode): Remove function. (after-init-hook): Add hook undelete-frame--handle-delete-frame to delete-frame-functions using after-init-hook to not store the initial frame. (undelete-frame): Remove undelete-frame-mode. Use undelete-frame-max instead of hard-coded 16. * lisp/menu-bar.el (menu-bar-file-menu): Remove menu item undelete-frame-mode. * src/frame.c (Fdelete_frame): Replace `undelete-frame-mode' with `undelete-frame-max' in the docstring. --- doc/emacs/frames.texi | 14 +++++---- etc/NEWS | 11 +++---- lisp/frame.el | 80 +++++++++++++++++++++++++-------------------------- lisp/menu-bar.el | 7 +---- src/frame.c | 2 +- 5 files changed, 55 insertions(+), 59 deletions(-) diff --git a/doc/emacs/frames.texi b/doc/emacs/frames.texi index c641b8ccb14..ba58f70caf3 100644 --- a/doc/emacs/frames.texi +++ b/doc/emacs/frames.texi @@ -515,12 +515,14 @@ error if there is only one frame. @item C-x 5 u @kindex C-x 5 u @findex undelete-frame -@findex undelete-frame-mode -When @code{undelete-frame-mode} is enabled, undelete one of the 16 -most recently deleted frames. Without a prefix argument, undelete the -most recently deleted frame. With a numerical prefix argument between -1 and 16, where 1 is the most recently deleted frame, undelete the -corresponding deleted frame. +@findex undelete-frame-max +Undelete one of the recently deleted frames. The user option +@code{undelete-frame-max} specifies the maximum number of deleted +frames to keep (the default is 1). Without a prefix argument, +undelete the most recently deleted frame. With a numerical prefix +argument between 1 and the number specified by @code{undelete-frame-max}, +where 1 is the most recently deleted frame, undelete the corresponding +deleted frame. @item C-z @kindex C-z @r{(X windows)} diff --git a/etc/NEWS b/etc/NEWS index 2e748ce7c5b..fdbfd9b1bea 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -287,11 +287,12 @@ height use 'window-height' in combination with 'body-lines'. +++ *** Deleted frames can now be undeleted. -The 16 most recently deleted frames can be undeleted with 'C-x 5 u' when -'undelete-frame-mode' is enabled. Without a prefix argument, undelete -the most recently deleted frame. With a numerical prefix argument -between 1 and 16, where 1 is the most recently deleted frame, undelete -the corresponding deleted frame. +The most recently deleted frame can be undeleted with 'C-x 5 u' when +the new user option 'undelete-frame-max' has its default value 1. +Without a prefix argument, undelete the most recently deleted frame. +With a numerical prefix argument between 1 and 'undelete-frame-max', +where 1 is the most recently deleted frame, undelete the corresponding +deleted frame. ** Tab Bars and Tab Lines diff --git a/lisp/frame.el b/lisp/frame.el index 599ffe591a5..5926a4d748b 100644 --- a/lisp/frame.el +++ b/lisp/frame.el @@ -2529,6 +2529,13 @@ deleting them." (if iconify (iconify-frame this) (delete-frame this))) (setq this next)))) + +(defcustom undelete-frame-max 1 + "Maximum number of deleted frames before oldest are thrown away." + :type 'integer + :group 'frames + :version "29.1") + (eval-when-compile (require 'frameset)) (defvar undelete-frame--deleted-frames nil @@ -2536,7 +2543,7 @@ deleting them." (defun undelete-frame--handle-delete-frame (frame) "Save the configuration of frames deleted with `delete-frame'. -Only the 16 most recently deleted frames are saved." +Only the `undelete-frame-max' most recently deleted frames are saved." (when (frame-live-p frame) (setq undelete-frame--deleted-frames (cons @@ -2555,54 +2562,45 @@ Only the 16 most recently deleted frames are saved." (cons '(display . :never) frameset-filter-alist)))) undelete-frame--deleted-frames)) - (if (> (length undelete-frame--deleted-frames) 16) + (if (> (length undelete-frame--deleted-frames) undelete-frame-max) (setq undelete-frame--deleted-frames (butlast undelete-frame--deleted-frames))))) -(define-minor-mode undelete-frame-mode - "Enable the `undelete-frame' command." - :group 'frames - :global t - (if undelete-frame-mode - (add-hook 'delete-frame-functions - #'undelete-frame--handle-delete-frame -75) - (remove-hook 'delete-frame-functions - #'undelete-frame--handle-delete-frame) - (setq undelete-frame--deleted-frames nil))) +(add-hook 'after-init-hook + (lambda () + (add-hook 'delete-frame-functions + #'undelete-frame--handle-delete-frame -75))) (defun undelete-frame (&optional arg) "Undelete a frame deleted with `delete-frame'. -Without a prefix argument, undelete the most recently deleted -frame. -With a numerical prefix argument ARG between 1 and 16, where 1 is -most recently deleted frame, undelete the ARGth deleted frame. +Without a prefix argument, undelete the most recently deleted frame. +With a numerical prefix argument ARG between 1 and `undelete-frame-max', +where 1 is most recently deleted frame, undelete the ARGth deleted frame. When called from Lisp, returns the new frame." (interactive "P") - (if (not undelete-frame-mode) - (user-error "Undelete-Frame mode is disabled") - (if (consp arg) - (user-error "Missing deleted frame number argument") - (let* ((number (pcase arg ('nil 1) ('- -1) (_ arg))) - (frames (frame-list)) - (frameset (nth (1- number) undelete-frame--deleted-frames)) - (graphic (display-graphic-p))) - (if (not (<= 1 number 16)) - (user-error "%d is not a valid deleted frame number argument" - number) - (if (not frameset) - (user-error "No deleted frame with number %d" number) - (if (not (eq graphic (car frameset))) - (user-error - "Cannot undelete a %s display frame on a %s display" - (if graphic "non-graphic" "graphic") - (if graphic "graphic" "non-graphic")) - (setq undelete-frame--deleted-frames - (delq frameset undelete-frame--deleted-frames)) - (frameset-restore (cdr frameset)) - (let ((frame (car (seq-difference (frame-list) frames)))) - (when frame - (select-frame-set-input-focus frame) - frame))))))))) + (if (consp arg) + (user-error "Missing deleted frame number argument") + (let* ((number (pcase arg ('nil 1) ('- -1) (_ arg))) + (frames (frame-list)) + (frameset (nth (1- number) undelete-frame--deleted-frames)) + (graphic (display-graphic-p))) + (if (not (<= 1 number undelete-frame-max)) + (user-error "%d is not a valid deleted frame number argument" + number) + (if (not frameset) + (user-error "No deleted frame with number %d" number) + (if (not (eq graphic (car frameset))) + (user-error + "Cannot undelete a %s display frame on a %s display" + (if graphic "non-graphic" "graphic") + (if graphic "graphic" "non-graphic")) + (setq undelete-frame--deleted-frames + (delq frameset undelete-frame--deleted-frames)) + (frameset-restore (cdr frameset)) + (let ((frame (car (seq-difference (frame-list) frames)))) + (when frame + (select-frame-set-input-focus frame) + frame)))))))) ;;; Window dividers. (defgroup window-divider nil diff --git a/lisp/menu-bar.el b/lisp/menu-bar.el index 36cbd6a9c51..e5a070b24ad 100644 --- a/lisp/menu-bar.el +++ b/lisp/menu-bar.el @@ -109,14 +109,9 @@ (bindings--define-key menu [separator-tab] menu-bar-separator)) - (bindings--define-key menu [enable-undelete-frame-mode] - '(menu-item "Enable Undeleting Frames" undelete-frame-mode - :visible (null undelete-frame-mode) - :help "Enable undeleting frames in this session")) (bindings--define-key menu [undelete-last-deleted-frame] '(menu-item "Undelete Frame" undelete-frame - :visible (and undelete-frame-mode - (car undelete-frame--deleted-frames)) + :visible (car undelete-frame--deleted-frames) :help "Undelete the most recently deleted frame")) ;; Don't use delete-frame as event name because that is a special diff --git a/src/frame.c b/src/frame.c index e5d74edc168..959f0c9c142 100644 --- a/src/frame.c +++ b/src/frame.c @@ -2385,7 +2385,7 @@ DEFUN ("delete-frame", Fdelete_frame, Sdelete_frame, 0, 2, "", doc: /* Delete FRAME, eliminating it from use. FRAME must be a live frame and defaults to the selected one. -When `undelete-frame-mode' is enabled, the 16 most recently deleted +When `undelete-frame-max' is more than 0, the most recently deleted frames can be undeleted with `undelete-frame', which see. A frame may not be deleted if its minibuffer serves as surrogate -- cgit v1.2.1 From e25db1e167c7322497a1e33590177d57571188c8 Mon Sep 17 00:00:00 2001 From: Po Lu Date: Mon, 17 Jan 2022 08:29:39 +0800 Subject: Exercise wire right after event is filtered for native input * src/xterm.c (handle_one_xevent): Run a no-op immediately after an event was filtered by GDK. --- src/xterm.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/xterm.c b/src/xterm.c index 3328e659301..9bf4404c9cf 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -8385,6 +8385,11 @@ x_filter_event (struct x_display_info *dpyinfo, XEvent *event) result = xg_filter_key (f1, event); unblock_input (); + if (result && f1) + /* There will probably be a GDK event generated soon, so + exercise the wire to make pselect return. */ + XNoOp (FRAME_X_DISPLAY (f1)); + return result; } -- cgit v1.2.1 From 84ebb165771f2e0b4218ffa77916953681f9901e Mon Sep 17 00:00:00 2001 From: Po Lu Date: Mon, 17 Jan 2022 09:48:01 +0800 Subject: Translate timestamps when using GTK native input * src/gtkutil.c (xg_widget_key_press_event_cb): Use timestamp specified in key event. (xg_filter_key): Translate timestamps. --- src/gtkutil.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/gtkutil.c b/src/gtkutil.c index 48e981d0d9a..3cb8cd15332 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -6151,6 +6151,7 @@ xg_widget_key_press_event_cb (GtkWidget *widget, GdkEvent *event, inev.ie.modifiers |= x_x_to_emacs_modifiers (FRAME_DISPLAY_INFO (f), xstate); + inev.ie.timestamp = event->key.time; if (event->key.is_modifier) goto done; @@ -6324,6 +6325,7 @@ xg_filter_key (struct frame *frame, XEvent *xkey) NULL, NULL, &consumed); xg_add_virtual_mods (dpyinfo, &xg_event->key); xg_event->key.state &= ~consumed; + xg_event->key.time = xkey->xkey.time; #if GTK_CHECK_VERSION (3, 6, 0) xg_event->key.is_modifier = gdk_x11_keymap_key_is_modifier (keymap, xg_event->key.hardware_keycode); @@ -6337,6 +6339,7 @@ xg_filter_key (struct frame *frame, XEvent *xkey) xg_event->key.hardware_keycode = xev->detail; xg_event->key.group = xev->group.effective; xg_event->key.state = xev->mods.effective; + xg_event->key.time = xev->time; gdk_keymap_translate_keyboard_state (keymap, xev->detail, xev->mods.effective, -- cgit v1.2.1 From ace6a88285a281b1d5590ab64d83be962419d976 Mon Sep 17 00:00:00 2001 From: Po Lu Date: Mon, 17 Jan 2022 04:52:00 +0000 Subject: Really eliminate tooltip flicker on Haiku * src/haikufns.c (tip_frame): Make non-static. * src/haikuterm.c (haiku_read_socket): Ignore motion events that didn't actually move when a tip frame is visible. * src/haikuterm.h (tip_frame): Declare. --- src/haikufns.c | 2 +- src/haikuterm.c | 10 ++++++++++ src/haikuterm.h | 2 ++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/haikufns.c b/src/haikufns.c index 52bb13bc89b..2edf883b9cb 100644 --- a/src/haikufns.c +++ b/src/haikufns.c @@ -45,7 +45,7 @@ along with GNU Emacs. If not, see . */ #define BLUE_FROM_ULONG(color) ((color) & 0xff) /* The frame of the currently visible tooltip. */ -static Lisp_Object tip_frame; +Lisp_Object tip_frame; /* The window-system window corresponding to the frame of the currently visible tooltip. */ diff --git a/src/haikuterm.c b/src/haikuterm.c index 05f9788f184..cc4c3961ec4 100644 --- a/src/haikuterm.c +++ b/src/haikuterm.c @@ -2786,6 +2786,16 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit) struct haiku_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); struct haiku_rect r = dpyinfo->last_mouse_glyph; + /* For an unknown reason Haiku sends phantom motion events when a + tooltip frame is visible. FIXME */ + if (FRAMEP (tip_frame) + && FRAME_LIVE_P (XFRAME (tip_frame)) + && FRAME_VISIBLE_P (XFRAME (tip_frame)) + && f == dpyinfo->last_mouse_motion_frame + && b->x == dpyinfo->last_mouse_motion_x + && b->y == dpyinfo->last_mouse_motion_y) + continue; + dpyinfo->last_mouse_motion_x = b->x; dpyinfo->last_mouse_motion_y = b->y; dpyinfo->last_mouse_motion_frame = f; diff --git a/src/haikuterm.h b/src/haikuterm.h index 3e39403ab4d..de302883e48 100644 --- a/src/haikuterm.h +++ b/src/haikuterm.h @@ -178,6 +178,8 @@ struct x_output extern struct haiku_display_info *x_display_list; extern struct font_driver const haikufont_driver; +extern Lisp_Object tip_frame; + struct scroll_bar { /* These fields are shared by all vectors. */ -- cgit v1.2.1 From c2f3a2f5e35db7f51a7c8f1f80225e3d4f140e0a Mon Sep 17 00:00:00 2001 From: Po Lu Date: Mon, 17 Jan 2022 05:06:31 +0000 Subject: * src/haikufns.c (Fx_show_tip): Sync after making window visible. --- src/haikufns.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/haikufns.c b/src/haikufns.c index 2edf883b9cb..c294f4e862c 100644 --- a/src/haikufns.c +++ b/src/haikufns.c @@ -2005,7 +2005,7 @@ DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0, FRAME_OUTPUT_DATA (XFRAME (frame))->current_cursor); SET_FRAME_VISIBLE (tip_f, 1); BWindow_set_visible (FRAME_HAIKU_WINDOW (tip_f), 1); - + BWindow_sync (FRAME_HAIKU_WINDOW (tip_f)); w->must_be_updated_p = true; flush_frame (tip_f); update_single_window (w); -- cgit v1.2.1 From 65666c47863c4ad2ed4bacd1a0bc5e638269df52 Mon Sep 17 00:00:00 2001 From: Juri Linkov Date: Mon, 17 Jan 2022 10:24:20 +0200 Subject: * etc/NEWS: Improve wording of 'undelete-frame-max' (bug#51883). --- etc/NEWS | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/etc/NEWS b/etc/NEWS index fdbfd9b1bea..3fdb6212156 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -287,12 +287,13 @@ height use 'window-height' in combination with 'body-lines'. +++ *** Deleted frames can now be undeleted. -The most recently deleted frame can be undeleted with 'C-x 5 u' when -the new user option 'undelete-frame-max' has its default value 1. -Without a prefix argument, undelete the most recently deleted frame. -With a numerical prefix argument between 1 and 'undelete-frame-max', -where 1 is the most recently deleted frame, undelete the corresponding -deleted frame. +The most recently deleted frame can be undeleted with 'C-x 5 u' +if the new user option 'undelete-frame-max' is a positive number. +This option specifies the maximum number of closed frames to remember. +The default is 1. Without a prefix argument, undelete the most +recently deleted frame. With a numerical prefix argument between 1 +and the value of 'undelete-frame-max', where 1 is the most recently +deleted frame, undelete the corresponding deleted frame. ** Tab Bars and Tab Lines -- cgit v1.2.1 From c9d06d080bb2bd012813d6e5ac1f3deb32ccb29f Mon Sep 17 00:00:00 2001 From: Michael Albinus Date: Mon, 17 Jan 2022 10:46:58 +0100 Subject: Improve handling of INFILE in tramp*-process-file (Bug#53284) * lisp/net/tramp-adb.el (tramp-adb-handle-process-file): * lisp/net/tramp-sh.el (tramp-sh-handle-process-file): * lisp/net/tramp-smb.el (tramp-smb-handle-process-file): * lisp/net/tramp-sshfs.el (tramp-sshfs-handle-process-file): Improve handling of INFILE. Fix thinko using `process-file-side-effects'. (Bug#53284) * lisp/net/tramp-sshfs.el (tramp-sshfs-file-name-handler-alist): Use `tramp-sshfs-handle-set-file-times'. (tramp-sshfs-handle-set-file-times): New defun. * test/lisp/net/tramp-tests.el (tramp-test28-process-file): Extend test. --- lisp/net/tramp-adb.el | 8 ++++---- lisp/net/tramp-sh.el | 8 ++++---- lisp/net/tramp-smb.el | 5 ++--- lisp/net/tramp-sshfs.el | 38 +++++++++++++++++++++++++++++++++----- test/lisp/net/tramp-tests.el | 14 +++++++++++++- 5 files changed, 56 insertions(+), 17 deletions(-) diff --git a/lisp/net/tramp-adb.el b/lisp/net/tramp-adb.el index ed73a86ef03..699dec4d58e 100644 --- a/lisp/net/tramp-adb.el +++ b/lisp/net/tramp-adb.el @@ -815,7 +815,7 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored." ;; Determine input. (if (null infile) (setq input (tramp-get-remote-null-device v)) - (setq infile (expand-file-name infile)) + (setq infile (tramp-compat-file-name-unquote (expand-file-name infile))) (if (tramp-equal-remote default-directory infile) ;; INFILE is on the same remote host. (setq input (tramp-file-local-name infile)) @@ -870,7 +870,8 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored." (setq ret (tramp-adb-send-command-and-check v (format "(cd %s; %s)" - (tramp-shell-quote-argument localname) command) + (tramp-unquote-shell-quote-argument localname) + command) t)) (unless (natnump ret) (setq ret 1)) ;; We should add the output anyway. @@ -900,8 +901,7 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored." ;; Cleanup. We remove all file cache values for the connection, ;; because the remote process could have changed them. (when tmpinput (delete-file tmpinput)) - - (unless process-file-side-effects + (when process-file-side-effects (tramp-flush-directory-properties v "")) ;; Return exit status. diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el index 72b1ebb3e06..ffa11b1fe3c 100644 --- a/lisp/net/tramp-sh.el +++ b/lisp/net/tramp-sh.el @@ -3098,7 +3098,7 @@ implementation will be used." ;; Determine input. (if (null infile) (setq input (tramp-get-remote-null-device v)) - (setq infile (expand-file-name infile)) + (setq infile (tramp-compat-file-name-unquote (expand-file-name infile))) (if (tramp-equal-remote default-directory infile) ;; INFILE is on the same remote host. (setq input (tramp-file-local-name infile)) @@ -3153,7 +3153,8 @@ implementation will be used." (setq ret (tramp-send-command-and-check v (format "cd %s && %s" - (tramp-shell-quote-argument localname) command) + (tramp-unquote-shell-quote-argument localname) + command) t t t)) (unless (natnump ret) (setq ret 1)) ;; We should add the output anyway. @@ -3184,8 +3185,7 @@ implementation will be used." ;; Cleanup. We remove all file cache values for the connection, ;; because the remote process could have changed them. (when tmpinput (delete-file tmpinput)) - - (unless process-file-side-effects + (when process-file-side-effects (tramp-flush-directory-properties v "")) ;; Return exit status. diff --git a/lisp/net/tramp-smb.el b/lisp/net/tramp-smb.el index c5f423fa3f0..6515519680c 100644 --- a/lisp/net/tramp-smb.el +++ b/lisp/net/tramp-smb.el @@ -1281,7 +1281,7 @@ component is used as the target of the symlink." ;; Determine input. (when infile - (setq infile (expand-file-name infile)) + (setq infile (tramp-compat-file-name-unquote (expand-file-name infile))) (if (tramp-equal-remote default-directory infile) ;; INFILE is on the same remote host. (setq input (tramp-file-local-name infile)) @@ -1373,8 +1373,7 @@ component is used as the target of the symlink." (when tmpinput (delete-file tmpinput)) (unless outbuf (kill-buffer (tramp-get-connection-property v "process-buffer" nil))) - - (unless process-file-side-effects + (when process-file-side-effects (tramp-flush-directory-properties v "")) ;; Return exit status. diff --git a/lisp/net/tramp-sshfs.el b/lisp/net/tramp-sshfs.el index 0a5bf2f43b3..8890d0ec5c3 100644 --- a/lisp/net/tramp-sshfs.el +++ b/lisp/net/tramp-sshfs.el @@ -137,7 +137,7 @@ (set-file-acl . ignore) (set-file-modes . tramp-sshfs-handle-set-file-modes) (set-file-selinux-context . ignore) - (set-file-times . ignore) + (set-file-times . tramp-sshfs-handle-set-file-times) (set-visited-file-modtime . tramp-handle-set-visited-file-modtime) (shell-command . tramp-handle-shell-command) (start-file-process . tramp-handle-start-file-process) @@ -242,13 +242,28 @@ arguments to pass to the OPERATION." (let ((command (format "cd %s && exec %s" - localname - (mapconcat #'tramp-shell-quote-argument (cons program args) " ")))) + (tramp-unquote-shell-quote-argument localname) + (mapconcat #'tramp-shell-quote-argument (cons program args) " "))) + input tmpinput) + + ;; Determine input. + (if (null infile) + (setq input (tramp-get-remote-null-device v)) + (setq infile (tramp-compat-file-name-unquote (expand-file-name infile))) + (if (tramp-equal-remote default-directory infile) + ;; INFILE is on the same remote host. + (setq input (tramp-file-local-name infile)) + ;; INFILE must be copied to remote host. + (setq input (tramp-make-tramp-temp-file v) + tmpinput (tramp-make-tramp-file-name v input 'nohop)) + (copy-file infile tmpinput t))) + (when input (setq command (format "%s <%s" command input))) + (unwind-protect (apply #'tramp-call-process v (tramp-get-method-parameter v 'tramp-login-program) - infile destination display + nil destination display (tramp-expand-args v 'tramp-login-args ?h (or (tramp-file-name-host v) "") @@ -256,7 +271,11 @@ arguments to pass to the OPERATION." ?p (or (tramp-file-name-port v) "") ?l command)) - (unless process-file-side-effects + ;; Cleanup. We remove all file cache values for the + ;; connection, because the remote process could have changed + ;; them. + (when tmpinput (delete-file tmpinput)) + (when process-file-side-effects (tramp-flush-directory-properties v "")))))) (defun tramp-sshfs-handle-rename-file @@ -285,6 +304,15 @@ arguments to pass to the OPERATION." (tramp-compat-set-file-modes (tramp-fuse-local-file-name filename) mode flag)))) +(defun tramp-sshfs-handle-set-file-times (filename &optional timestamp flag) + "Like `set-file-times' for Tramp files." + (or (file-exists-p filename) (write-region "" nil filename nil 0)) + (with-parsed-tramp-file-name filename nil + (unless (and (eq flag 'nofollow) (file-symlink-p filename)) + (tramp-flush-file-properties v localname) + (tramp-compat-set-file-times + (tramp-fuse-local-file-name filename) timestamp flag)))) + (defun tramp-sshfs-handle-write-region (start end filename &optional append visit lockname mustbenew) "Like `write-region' for Tramp files." diff --git a/test/lisp/net/tramp-tests.el b/test/lisp/net/tramp-tests.el index ea0ff3c760e..a07d749916e 100644 --- a/test/lisp/net/tramp-tests.el +++ b/test/lisp/net/tramp-tests.el @@ -4504,7 +4504,19 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'." (should (string-equal (format "%s\n%s\n" fnnd fnnd) (buffer-string))) ;; A non-nil DISPLAY must not raise the buffer. - (should-not (get-buffer-window (current-buffer) t)))) + (should-not (get-buffer-window (current-buffer) t)) + (delete-file tmp-name)) + + ;; Check remote and local INFILE. + (dolist (local '(nil t)) + (with-temp-buffer + (setq tmp-name (tramp--test-make-temp-name local quoted)) + (write-region "foo" nil tmp-name) + (should (file-exists-p tmp-name)) + (should (zerop (process-file "cat" tmp-name t))) + (should (string-equal "foo" (buffer-string))) + (should-not (get-buffer-window (current-buffer) t))) + (delete-file tmp-name))) ;; Cleanup. (ignore-errors (delete-file tmp-name)))))) -- cgit v1.2.1 From 2fa1eced39f0e1b5495f3c582ee938e1e1dddcaf Mon Sep 17 00:00:00 2001 From: Po Lu Date: Mon, 17 Jan 2022 10:08:04 +0000 Subject: Display override redirect frames in all workspaces on Haiku * src/haiku_support.cc (class EmacsWindow): New field `pre_override_redirect_workspaces'. (BWindow_set_override_redirect): Set window to display on all workspaces. --- src/haiku_support.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/haiku_support.cc b/src/haiku_support.cc index 22605335c55..0f4ec2cd7c3 100644 --- a/src/haiku_support.cc +++ b/src/haiku_support.cc @@ -406,6 +406,7 @@ public: bool menu_bar_active_p = false; window_look pre_override_redirect_style; window_feel pre_override_redirect_feel; + uint32 pre_override_redirect_workspaces; EmacsWindow () : BWindow (BRect (0, 0, 0, 0), "", B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, B_NO_SERVER_SIDE_WINDOW_MODIFIERS) @@ -3170,11 +3171,14 @@ BWindow_set_override_redirect (void *window, bool override_redirect_p) w->pre_override_redirect_style = w->Look (); w->SetFeel (kMenuWindowFeel); w->SetLook (B_NO_BORDER_WINDOW_LOOK); + w->pre_override_redirect_workspaces = w->Workspaces (); + w->SetWorkspaces (B_ALL_WORKSPACES); } else { w->SetFeel (w->pre_override_redirect_feel); w->SetLook (w->pre_override_redirect_style); + w->SetWorkspaces (w->pre_override_redirect_workspaces); } w->UnlockLooper (); -- cgit v1.2.1 From 1cd6737a38723f482db73a8e4739176a0d524c57 Mon Sep 17 00:00:00 2001 From: Po Lu Date: Mon, 17 Jan 2022 10:46:55 +0000 Subject: Use BControlLook to determine scroll bar size on Haiku * src/haiku_support.cc (BScrollBar_default_size): Use BControlLook instead of legacy constants. --- src/haiku_support.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/haiku_support.cc b/src/haiku_support.cc index 0f4ec2cd7c3..22a977a4a69 100644 --- a/src/haiku_support.cc +++ b/src/haiku_support.cc @@ -36,6 +36,7 @@ along with GNU Emacs. If not, see . */ #include #include #include +#include #include @@ -2019,7 +2020,9 @@ BView_scroll_bar_update (void *sb, int portion, int whole, int position) int BScrollBar_default_size (int horizontal_p) { - return horizontal_p ? B_H_SCROLL_BAR_HEIGHT : B_V_SCROLL_BAR_WIDTH; + return be_control_look->GetScrollBarWidth (horizontal_p + ? B_HORIZONTAL + : B_VERTICAL); } /* Invalidate VIEW, causing it to be drawn again. */ -- cgit v1.2.1 From 9e64aeff40872e5080fa04015234103cb9bcf3bf Mon Sep 17 00:00:00 2001 From: Andrea Corallo Date: Tue, 28 Dec 2021 12:12:16 +0100 Subject: * Fix native comp for non trivial function names (bug#52833) * lisp/emacs-lisp/comp.el (comp-c-func-name): Fix native compilation for functions with function names containing non trivial characters (bug#52833). This commit is the backport of e7699bf290. Do not merge to master --- lisp/emacs-lisp/comp.el | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lisp/emacs-lisp/comp.el b/lisp/emacs-lisp/comp.el index 2ced6277add..a363bed3642 100644 --- a/lisp/emacs-lisp/comp.el +++ b/lisp/emacs-lisp/comp.el @@ -1181,7 +1181,9 @@ clashes." for i across orig-name for byte = (format "%x" i) do (aset str j (aref byte 0)) - (aset str (1+ j) (aref byte 1)) + (aset str (1+ j) (if (length> byte 1) + (aref byte 1) + ?\_)) finally return str)) (human-readable (string-replace "-" "_" orig-name)) -- cgit v1.2.1 From 412247c53f3708e96f7a16aaeee55a747a91d22d Mon Sep 17 00:00:00 2001 From: Po Lu Date: Mon, 17 Jan 2022 11:09:50 +0000 Subject: Fix Emacs icon not appearing on Haiku * lib-src/be_resources.cc (main): Scale input bitmap appropriately before setting it as the mini and large icons. * src/Makefile.in (Emacs): Add dependency on `lib-src/be-resources'. --- lib-src/be_resources.cc | 39 ++++++++++++++++++++++++++++++++++++--- src/Makefile.in | 2 +- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/lib-src/be_resources.cc b/lib-src/be_resources.cc index d18fe30dd7a..414f91a192d 100644 --- a/lib-src/be_resources.cc +++ b/lib-src/be_resources.cc @@ -29,6 +29,9 @@ along with GNU Emacs. If not, see . */ #include #include #include +#include +#include +#include using namespace std; @@ -79,11 +82,25 @@ main (int argc, char **argv) BApplication app ("application/x-vnd.GNU-emacs-resource-helper"); BFile file; BBitmap *icon; + BBitmap scale32 (BRect (0, 0, 31, 31), B_RGBA32, true); + BBitmap scale16 (BRect (0, 0, 15, 15), B_RGBA32, true); BAppFileInfo info; status_t code; struct version_info vinfo; char *v = strdup (PACKAGE_VERSION); + if (scale32.InitCheck () != B_OK + || scale16.InitCheck () != B_OK) + { + fprintf (stderr, "Bitmap initialization ran out of memory\n"); + return EXIT_FAILURE; + } + + BView scale32view (scale32.Bounds (), NULL, + B_FOLLOW_NONE, B_WILL_DRAW); + BView scale16view (scale16.Bounds (), NULL, + B_FOLLOW_NONE, B_WILL_DRAW); + if (argc != 3) { printf ("be-resources ICON FILE: make FILE appropriate for Emacs.\n"); @@ -117,8 +134,24 @@ main (int argc, char **argv) return EXIT_FAILURE; } - info.SetIcon (icon, B_MINI_ICON); - info.SetIcon (icon, B_LARGE_ICON); + scale32.AddChild (&scale32view); + scale16.AddChild (&scale16view); + + if (!scale32view.LockLooper () + || !scale16view.LockLooper ()) + { + fprintf (stderr, "Failed to lock bitmap looper\n"); + return EXIT_FAILURE; + } + + scale32view.DrawBitmapAsync (icon, scale32.Bounds ()); + scale16view.DrawBitmapAsync (icon, scale16.Bounds ()); + + scale32view.Sync (); + scale16view.Sync (); + + info.SetIcon (&scale16, B_MINI_ICON); + info.SetIcon (&scale32, B_LARGE_ICON); info.SetSignature ("application/x-vnd.GNU-emacs"); v = strtok (v, "."); @@ -140,5 +173,5 @@ main (int argc, char **argv) info.SetVersionInfo (&vinfo, B_APP_VERSION_KIND); - return EXIT_SUCCESS; + exit (EXIT_SUCCESS); } diff --git a/src/Makefile.in b/src/Makefile.in index 04fabd5f424..0b465b8cd6f 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -616,7 +616,7 @@ endif ## icon set. ifeq ($(HAVE_BE_APP),yes) -Emacs: emacs$(EXEEXT) +Emacs: emacs$(EXEEXT) $(libsrc)/be-resources $(AM_V_GEN) cp -f emacs$(EXEEXT) $@ $(AM_V_at) $(libsrc)/be-resources \ $(etc)/images/icons/hicolor/32x32/apps/emacs.png $@ -- cgit v1.2.1 From 37d46cec603dd7029485903806f6bf6cfd2335f7 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Mon, 17 Jan 2022 14:51:03 +0200 Subject: Revert "* etc/NEWS: Improve wording of 'undelete-frame-max' (bug#51883)." This reverts commit 65666c47863c4ad2ed4bacd1a0bc5e638269df52. The original commit was unilateral and disregarded past discussions. --- etc/NEWS | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/etc/NEWS b/etc/NEWS index 3fdb6212156..fdbfd9b1bea 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -287,13 +287,12 @@ height use 'window-height' in combination with 'body-lines'. +++ *** Deleted frames can now be undeleted. -The most recently deleted frame can be undeleted with 'C-x 5 u' -if the new user option 'undelete-frame-max' is a positive number. -This option specifies the maximum number of closed frames to remember. -The default is 1. Without a prefix argument, undelete the most -recently deleted frame. With a numerical prefix argument between 1 -and the value of 'undelete-frame-max', where 1 is the most recently -deleted frame, undelete the corresponding deleted frame. +The most recently deleted frame can be undeleted with 'C-x 5 u' when +the new user option 'undelete-frame-max' has its default value 1. +Without a prefix argument, undelete the most recently deleted frame. +With a numerical prefix argument between 1 and 'undelete-frame-max', +where 1 is the most recently deleted frame, undelete the corresponding +deleted frame. ** Tab Bars and Tab Lines -- cgit v1.2.1 From 8cc1b9035cbe12c684139de0ad1590661ea45c3c Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Mon, 17 Jan 2022 14:51:53 +0200 Subject: Revert "Add undelete-frame-max instead of undelete-frame-mode (bug#51883)" This reverts commit 714e11d53534416b6519396a9df5d62054731810. That commit was unilateral and disregarded past discussions. --- doc/emacs/frames.texi | 14 ++++----- etc/NEWS | 11 ++++--- lisp/frame.el | 80 ++++++++++++++++++++++++++------------------------- lisp/menu-bar.el | 7 ++++- src/frame.c | 2 +- 5 files changed, 59 insertions(+), 55 deletions(-) diff --git a/doc/emacs/frames.texi b/doc/emacs/frames.texi index ba58f70caf3..c641b8ccb14 100644 --- a/doc/emacs/frames.texi +++ b/doc/emacs/frames.texi @@ -515,14 +515,12 @@ error if there is only one frame. @item C-x 5 u @kindex C-x 5 u @findex undelete-frame -@findex undelete-frame-max -Undelete one of the recently deleted frames. The user option -@code{undelete-frame-max} specifies the maximum number of deleted -frames to keep (the default is 1). Without a prefix argument, -undelete the most recently deleted frame. With a numerical prefix -argument between 1 and the number specified by @code{undelete-frame-max}, -where 1 is the most recently deleted frame, undelete the corresponding -deleted frame. +@findex undelete-frame-mode +When @code{undelete-frame-mode} is enabled, undelete one of the 16 +most recently deleted frames. Without a prefix argument, undelete the +most recently deleted frame. With a numerical prefix argument between +1 and 16, where 1 is the most recently deleted frame, undelete the +corresponding deleted frame. @item C-z @kindex C-z @r{(X windows)} diff --git a/etc/NEWS b/etc/NEWS index fdbfd9b1bea..2e748ce7c5b 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -287,12 +287,11 @@ height use 'window-height' in combination with 'body-lines'. +++ *** Deleted frames can now be undeleted. -The most recently deleted frame can be undeleted with 'C-x 5 u' when -the new user option 'undelete-frame-max' has its default value 1. -Without a prefix argument, undelete the most recently deleted frame. -With a numerical prefix argument between 1 and 'undelete-frame-max', -where 1 is the most recently deleted frame, undelete the corresponding -deleted frame. +The 16 most recently deleted frames can be undeleted with 'C-x 5 u' when +'undelete-frame-mode' is enabled. Without a prefix argument, undelete +the most recently deleted frame. With a numerical prefix argument +between 1 and 16, where 1 is the most recently deleted frame, undelete +the corresponding deleted frame. ** Tab Bars and Tab Lines diff --git a/lisp/frame.el b/lisp/frame.el index 5926a4d748b..599ffe591a5 100644 --- a/lisp/frame.el +++ b/lisp/frame.el @@ -2529,13 +2529,6 @@ deleting them." (if iconify (iconify-frame this) (delete-frame this))) (setq this next)))) - -(defcustom undelete-frame-max 1 - "Maximum number of deleted frames before oldest are thrown away." - :type 'integer - :group 'frames - :version "29.1") - (eval-when-compile (require 'frameset)) (defvar undelete-frame--deleted-frames nil @@ -2543,7 +2536,7 @@ deleting them." (defun undelete-frame--handle-delete-frame (frame) "Save the configuration of frames deleted with `delete-frame'. -Only the `undelete-frame-max' most recently deleted frames are saved." +Only the 16 most recently deleted frames are saved." (when (frame-live-p frame) (setq undelete-frame--deleted-frames (cons @@ -2562,45 +2555,54 @@ Only the `undelete-frame-max' most recently deleted frames are saved." (cons '(display . :never) frameset-filter-alist)))) undelete-frame--deleted-frames)) - (if (> (length undelete-frame--deleted-frames) undelete-frame-max) + (if (> (length undelete-frame--deleted-frames) 16) (setq undelete-frame--deleted-frames (butlast undelete-frame--deleted-frames))))) -(add-hook 'after-init-hook - (lambda () - (add-hook 'delete-frame-functions - #'undelete-frame--handle-delete-frame -75))) +(define-minor-mode undelete-frame-mode + "Enable the `undelete-frame' command." + :group 'frames + :global t + (if undelete-frame-mode + (add-hook 'delete-frame-functions + #'undelete-frame--handle-delete-frame -75) + (remove-hook 'delete-frame-functions + #'undelete-frame--handle-delete-frame) + (setq undelete-frame--deleted-frames nil))) (defun undelete-frame (&optional arg) "Undelete a frame deleted with `delete-frame'. -Without a prefix argument, undelete the most recently deleted frame. -With a numerical prefix argument ARG between 1 and `undelete-frame-max', -where 1 is most recently deleted frame, undelete the ARGth deleted frame. +Without a prefix argument, undelete the most recently deleted +frame. +With a numerical prefix argument ARG between 1 and 16, where 1 is +most recently deleted frame, undelete the ARGth deleted frame. When called from Lisp, returns the new frame." (interactive "P") - (if (consp arg) - (user-error "Missing deleted frame number argument") - (let* ((number (pcase arg ('nil 1) ('- -1) (_ arg))) - (frames (frame-list)) - (frameset (nth (1- number) undelete-frame--deleted-frames)) - (graphic (display-graphic-p))) - (if (not (<= 1 number undelete-frame-max)) - (user-error "%d is not a valid deleted frame number argument" - number) - (if (not frameset) - (user-error "No deleted frame with number %d" number) - (if (not (eq graphic (car frameset))) - (user-error - "Cannot undelete a %s display frame on a %s display" - (if graphic "non-graphic" "graphic") - (if graphic "graphic" "non-graphic")) - (setq undelete-frame--deleted-frames - (delq frameset undelete-frame--deleted-frames)) - (frameset-restore (cdr frameset)) - (let ((frame (car (seq-difference (frame-list) frames)))) - (when frame - (select-frame-set-input-focus frame) - frame)))))))) + (if (not undelete-frame-mode) + (user-error "Undelete-Frame mode is disabled") + (if (consp arg) + (user-error "Missing deleted frame number argument") + (let* ((number (pcase arg ('nil 1) ('- -1) (_ arg))) + (frames (frame-list)) + (frameset (nth (1- number) undelete-frame--deleted-frames)) + (graphic (display-graphic-p))) + (if (not (<= 1 number 16)) + (user-error "%d is not a valid deleted frame number argument" + number) + (if (not frameset) + (user-error "No deleted frame with number %d" number) + (if (not (eq graphic (car frameset))) + (user-error + "Cannot undelete a %s display frame on a %s display" + (if graphic "non-graphic" "graphic") + (if graphic "graphic" "non-graphic")) + (setq undelete-frame--deleted-frames + (delq frameset undelete-frame--deleted-frames)) + (frameset-restore (cdr frameset)) + (let ((frame (car (seq-difference (frame-list) frames)))) + (when frame + (select-frame-set-input-focus frame) + frame))))))))) ;;; Window dividers. (defgroup window-divider nil diff --git a/lisp/menu-bar.el b/lisp/menu-bar.el index e5a070b24ad..36cbd6a9c51 100644 --- a/lisp/menu-bar.el +++ b/lisp/menu-bar.el @@ -109,9 +109,14 @@ (bindings--define-key menu [separator-tab] menu-bar-separator)) + (bindings--define-key menu [enable-undelete-frame-mode] + '(menu-item "Enable Undeleting Frames" undelete-frame-mode + :visible (null undelete-frame-mode) + :help "Enable undeleting frames in this session")) (bindings--define-key menu [undelete-last-deleted-frame] '(menu-item "Undelete Frame" undelete-frame - :visible (car undelete-frame--deleted-frames) + :visible (and undelete-frame-mode + (car undelete-frame--deleted-frames)) :help "Undelete the most recently deleted frame")) ;; Don't use delete-frame as event name because that is a special diff --git a/src/frame.c b/src/frame.c index 959f0c9c142..e5d74edc168 100644 --- a/src/frame.c +++ b/src/frame.c @@ -2385,7 +2385,7 @@ DEFUN ("delete-frame", Fdelete_frame, Sdelete_frame, 0, 2, "", doc: /* Delete FRAME, eliminating it from use. FRAME must be a live frame and defaults to the selected one. -When `undelete-frame-max' is more than 0, the most recently deleted +When `undelete-frame-mode' is enabled, the 16 most recently deleted frames can be undeleted with `undelete-frame', which see. A frame may not be deleted if its minibuffer serves as surrogate -- cgit v1.2.1 From f393d0d441c3746f98007ae54341870a296bf809 Mon Sep 17 00:00:00 2001 From: Po Lu Date: Mon, 17 Jan 2022 21:42:31 +0800 Subject: Fix regression leading to flickering tooltips when the mouse is moved * lisp/tooltip.el (tooltip-show-help): Compare string with previous tooltip string ignoring properties. --- lisp/tooltip.el | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lisp/tooltip.el b/lisp/tooltip.el index 1840016d7cf..d1628842307 100644 --- a/lisp/tooltip.el +++ b/lisp/tooltip.el @@ -378,9 +378,12 @@ MSG is either a help string to display, or nil to cancel the display." ;; Cancel display. This also cancels a delayed tip, if ;; there is one. (tooltip-hide)) - ((equal-including-properties previous-help msg) - ;; Same help as before (but possibly the mouse has moved). - ;; Keep what we have. + ((equal previous-help msg) + ;; Same help as before (but possibly the mouse has + ;; moved or the text properties have changed). Keep + ;; what we have. If only text properties have changed, + ;; the tooltip won't be updated, but that shouldn't + ;; occur. ) (t ;; A different help. Remove a previous tooltip, and -- cgit v1.2.1 From 39d4e1ca21f3270d4835d5efa8862efc618c4cd9 Mon Sep 17 00:00:00 2001 From: Lars Ingebrigtsen Date: Mon, 17 Jan 2022 12:40:43 +0100 Subject: Move the Gnus range functions to a new range.el file * lisp/emacs-lisp/range.el: New file. * lisp/gnus/gnus-agent.el (range): (gnus-agent-synchronize-group-flags): (gnus-agent-possibly-alter-active): (gnus-agent-fetch-headers): (gnus-agent-read-agentview): (gnus-agent-fetch-group-1): (gnus-agent-read-p): (gnus-agent-expire-group-1): (gnus-agent-retrieve-headers): Adjust callers. * lisp/gnus/gnus-art.el (range): (gnus-article-describe-bindings): * lisp/gnus/gnus-cloud.el (range): (gnus-cloud-available-chunks): * lisp/gnus/gnus-draft.el (gnus-group-send-queue): * lisp/gnus/gnus-group.el (range): (gnus-group-line-format-alist): (gnus-number-of-unseen-articles-in-group): (gnus-group-update-eval-form): (gnus-group-read-group): (gnus-group-delete-articles): (gnus-group-catchup): (gnus-group-expire-articles-1): (gnus-add-marked-articles): * lisp/gnus/gnus-int.el (gnus-request-marks): * lisp/gnus/gnus-kill.el (gnus-apply-kill-file-internal): * lisp/gnus/gnus-range.el (gnus-range-difference) (gnus-sorted-range-intersection, gnus-uncompress-range) (gnus-add-to-range, gnus-remove-from-range) (gnus-member-of-range, gnus-list-range-intersection) (gnus-list-range-difference, gnus-range-length, gnus-range-add) (gnus-range-map): Make into obsolete aliases. * lisp/gnus/gnus-start.el (gnus-make-articles-unread): (gnus-convert-old-ticks): (gnus-read-old-newsrc-el-file): * lisp/gnus/gnus-sum.el (gnus-select-newsgroup): (gnus-articles-to-read): (gnus-articles-to-read): (gnus-killed-articles): (gnus-adjust-marked-articles): (gnus-update-marks): (gnus-update-marks): (gnus-compute-read-articles): (gnus-list-of-read-articles): (gnus-summary-update-info): (gnus-summary-move-article): (gnus-summary-expire-articles): (gnus-update-read-articles): (gnus-summary-insert-old-articles): (gnus-summary-insert-old-articles): (gnus-summary-insert-old-articles): * lisp/gnus/mail-source.el (gnus-range): (gnus-compress-sequence): * lisp/gnus/nnheader.el (range): (gnus-range-add): (nnheader-update-marks-actions): * lisp/gnus/nnimap.el (nnimap-update-info): (nnimap-update-info): (nnimap-update-info): (nnimap-update-qresync-info): (nnimap-update-qresync-info): (nnimap-update-qresync-info): (nnimap-parse-copied-articles): * lisp/gnus/nnmaildir.el (nnmaildir-request-update-info): (nnmaildir-request-update-info): (nnmaildir-request-expire-articles): (nnmaildir-request-expire-articles): (nnmaildir-request-set-mark): * lisp/gnus/nnmairix.el (nnmairix-request-set-mark): * lisp/gnus/nnmbox.el (nnmbox-record-active-article): (nnmbox-record-deleted-article): * lisp/gnus/nnml.el (nnml-request-compact-group): * lisp/gnus/nnvirtual.el (nnvirtual-request-expire-articles): * lisp/gnus/nnselect.el (numbers-by-group): (nnselect-request-update-info): (nnselect-push-info): --- lisp/emacs-lisp/range.el | 467 ++++++++++++++++++++++++++++++++++++ lisp/gnus/gnus-agent.el | 45 ++-- lisp/gnus/gnus-art.el | 3 +- lisp/gnus/gnus-cloud.el | 3 +- lisp/gnus/gnus-draft.el | 2 +- lisp/gnus/gnus-group.el | 52 ++-- lisp/gnus/gnus-int.el | 2 +- lisp/gnus/gnus-kill.el | 2 +- lisp/gnus/gnus-range.el | 443 +++------------------------------- lisp/gnus/gnus-start.el | 14 +- lisp/gnus/gnus-sum.el | 64 +++-- lisp/gnus/mail-source.el | 3 +- lisp/gnus/nnheader.el | 8 +- lisp/gnus/nnimap.el | 29 ++- lisp/gnus/nnmaildir.el | 16 +- lisp/gnus/nnmairix.el | 2 +- lisp/gnus/nnmbox.el | 6 +- lisp/gnus/nnml.el | 19 +- lisp/gnus/nnselect.el | 30 +-- lisp/gnus/nnvirtual.el | 2 +- test/lisp/emacs-lisp/range-tests.el | 65 +++++ 21 files changed, 710 insertions(+), 567 deletions(-) create mode 100644 lisp/emacs-lisp/range.el create mode 100644 test/lisp/emacs-lisp/range-tests.el diff --git a/lisp/emacs-lisp/range.el b/lisp/emacs-lisp/range.el new file mode 100644 index 00000000000..38c2866cd4c --- /dev/null +++ b/lisp/emacs-lisp/range.el @@ -0,0 +1,467 @@ +;;; ranges.el --- range functions -*- lexical-binding: t; -*- + +;; Copyright (C) 1996-2022 Free Software Foundation, Inc. + +;; Author: Lars Magne Ingebrigtsen + +;; This file is part of GNU Emacs. + +;; GNU Emacs 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. + +;; GNU Emacs 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 GNU Emacs. If not, see . + +;;; Commentary: + +;; A "range" is a list that represents a list of integers. A range is +;; a list containing cons cells of start/end pairs, as well as integers. +;; +;; ((2 . 5) 9 (11 . 13)) +;; +;; represents the list (2 3 4 5 9 11 12 13). + +;;; Code: + +(defun range-normalize (range) + "Normalize RANGE. +If RANGE is a single range, return (RANGE). Otherwise, return RANGE." + (if (listp (cdr-safe range)) + range + (list range))) + +(defun range-denormalize (range) + "If RANGE contains a single range, then return that. +If not, return RANGE as is." + (if (and (consp (car range)) + (length= range 1)) + (car range) + range)) + +(defun range-difference (range1 range2) + "Return the range of elements in RANGE1 that do not appear in RANGE2. +Both ranges must be in ascending order." + (setq range1 (range-normalize range1)) + (setq range2 (range-normalize range2)) + (let* ((new-range (cons nil (copy-sequence range1))) + (r new-range)) + (while (cdr r) + (let* ((r1 (cadr r)) + (r2 (car range2)) + (min1 (if (numberp r1) r1 (car r1))) + (max1 (if (numberp r1) r1 (cdr r1))) + (min2 (if (numberp r2) r2 (car r2))) + (max2 (if (numberp r2) r2 (cdr r2)))) + + (cond ((> min1 max1) + ;; Invalid range: may result from overlap condition (below) + ;; remove Invalid range + (setcdr r (cddr r))) + ((and (= min1 max1) + (listp r1)) + ;; Inefficient representation: may result from overlap + ;; condition (below) + (setcar (cdr r) min1)) + ((not min2) + ;; All done with range2 + (setq r nil)) + ((< max1 min2) + ;; No overlap: range1 precedes range2 + (pop r)) + ((< max2 min1) + ;; No overlap: range2 precedes range1 + (pop range2)) + ((and (<= min2 min1) (<= max1 max2)) + ;; Complete overlap: range1 removed + (setcdr r (cddr r))) + (t + (setcdr r (nconc (list (cons min1 (1- min2)) + (cons (1+ max2) max1)) + (cddr r))))))) + (cdr new-range))) + +(defun range-intersection (range1 range2) + "Return intersection of RANGE1 and RANGE2." + (let* (out + (min1 (car range1)) + (max1 (if (numberp min1) + (if (numberp (cdr range1)) + (prog1 (cdr range1) + (setq range1 nil)) min1) + (prog1 (cdr min1) + (setq min1 (car min1))))) + (min2 (car range2)) + (max2 (if (numberp min2) + (if (numberp (cdr range2)) + (prog1 (cdr range2) + (setq range2 nil)) min2) + (prog1 (cdr min2) + (setq min2 (car min2)))))) + (setq range1 (cdr range1) + range2 (cdr range2)) + (while (and min1 min2) + (cond ((< max1 min2) ; range1 precedes range2 + (setq range1 (cdr range1) + min1 nil)) + ((< max2 min1) ; range2 precedes range1 + (setq range2 (cdr range2) + min2 nil)) + (t ; some sort of overlap is occurring + (let ((min (max min1 min2)) + (max (min max1 max2))) + (setq out (if (= min max) + (cons min out) + (cons (cons min max) out)))) + (if (< max1 max2) ; range1 ends before range2 + (setq min1 nil) ; incr range1 + (setq min2 nil)))) ; incr range2 + (unless min1 + (setq min1 (car range1) + max1 (if (numberp min1) min1 + (prog1 (cdr min1) (setq min1 (car min1)))) + range1 (cdr range1))) + (unless min2 + (setq min2 (car range2) + max2 (if (numberp min2) min2 + (prog1 (cdr min2) (setq min2 (car min2)))) + range2 (cdr range2)))) + (cond ((cdr out) + (nreverse out)) + ((numberp (car out)) + out) + (t + (car out))))) + +(defun range-compress-list (numbers) + "Convert a sorted list of numbers to a range list." + (let ((first (car numbers)) + (last (car numbers)) + result) + (cond + ((null numbers) + nil) + ((not (listp (cdr numbers))) + numbers) + (t + (while numbers + (cond ((= last (car numbers)) nil) ;Omit duplicated number + ((= (1+ last) (car numbers)) ;Still in sequence + (setq last (car numbers))) + (t ;End of one sequence + (setq result + (cons (if (= first last) first + (cons first last)) + result)) + (setq first (car numbers)) + (setq last (car numbers)))) + (setq numbers (cdr numbers))) + (nreverse (cons (if (= first last) first (cons first last)) + result)))))) + +(defun range-uncompress (ranges) + "Expand a list of ranges into a list of numbers. +RANGES is either a single range on the form `(num . num)' or a list of +these ranges." + (let (first last result) + (cond + ((null ranges) + nil) + ((not (listp (cdr ranges))) + (setq first (car ranges)) + (setq last (cdr ranges)) + (while (<= first last) + (setq result (cons first result)) + (setq first (1+ first))) + (nreverse result)) + (t + (while ranges + (if (atom (car ranges)) + (when (numberp (car ranges)) + (setq result (cons (car ranges) result))) + (setq first (caar ranges)) + (setq last (cdar ranges)) + (while (<= first last) + (setq result (cons first result)) + (setq first (1+ first)))) + (setq ranges (cdr ranges))) + (nreverse result))))) + +(defun range-add-list (ranges list) + "Return a list of ranges that has all articles from both RANGES and LIST. +Note: LIST has to be sorted over `<'." + (if (not ranges) + (range-compress-list list) + (setq list (copy-sequence list)) + (unless (listp (cdr ranges)) + (setq ranges (list ranges))) + (let ((out ranges) + ilist lowest highest temp) + (while (and ranges list) + (setq ilist list) + (setq lowest (or (and (atom (car ranges)) (car ranges)) + (caar ranges))) + (while (and list (cdr list) (< (cadr list) lowest)) + (setq list (cdr list))) + (when (< (car ilist) lowest) + (setq temp list) + (setq list (cdr list)) + (setcdr temp nil) + (setq out (nconc (range-compress-list ilist) out))) + (setq highest (or (and (atom (car ranges)) (car ranges)) + (cdar ranges))) + (while (and list (<= (car list) highest)) + (setq list (cdr list))) + (setq ranges (cdr ranges))) + (when list + (setq out (nconc (range-compress-list list) out))) + (setq out (sort out (lambda (r1 r2) + (< (or (and (atom r1) r1) (car r1)) + (or (and (atom r2) r2) (car r2)))))) + (setq ranges out) + (while ranges + (if (atom (car ranges)) + (when (cdr ranges) + (if (atom (cadr ranges)) + (when (= (1+ (car ranges)) (cadr ranges)) + (setcar ranges (cons (car ranges) + (cadr ranges))) + (setcdr ranges (cddr ranges))) + (when (= (1+ (car ranges)) (caadr ranges)) + (setcar (cadr ranges) (car ranges)) + (setcar ranges (cadr ranges)) + (setcdr ranges (cddr ranges))))) + (when (cdr ranges) + (if (atom (cadr ranges)) + (when (= (1+ (cdar ranges)) (cadr ranges)) + (setcdr (car ranges) (cadr ranges)) + (setcdr ranges (cddr ranges))) + (when (= (1+ (cdar ranges)) (caadr ranges)) + (setcdr (car ranges) (cdadr ranges)) + (setcdr ranges (cddr ranges)))))) + (setq ranges (cdr ranges))) + out))) + +(defun range-remove (range1 range2) + "Return a range that has all articles from RANGE2 removed from RANGE1. +The returned range is always a list. RANGE2 can also be a unsorted +list of articles. RANGE1 is modified by side effects, RANGE2 is not +modified." + (if (or (null range1) (null range2)) + range1 + (let (out r1 r2 r1-min r1-max r2-min r2-max + (range2 (copy-tree range2))) + (setq range1 (if (listp (cdr range1)) range1 (list range1)) + range2 (sort (if (listp (cdr range2)) range2 (list range2)) + (lambda (e1 e2) + (< (if (consp e1) (car e1) e1) + (if (consp e2) (car e2) e2)))) + r1 (car range1) + r2 (car range2) + r1-min (if (consp r1) (car r1) r1) + r1-max (if (consp r1) (cdr r1) r1) + r2-min (if (consp r2) (car r2) r2) + r2-max (if (consp r2) (cdr r2) r2)) + (while (and range1 range2) + (cond ((< r2-max r1-min) ; r2 < r1 + (pop range2) + (setq r2 (car range2) + r2-min (if (consp r2) (car r2) r2) + r2-max (if (consp r2) (cdr r2) r2))) + ((and (<= r2-min r1-min) (<= r1-max r2-max)) ; r2 overlap r1 + (pop range1) + (setq r1 (car range1) + r1-min (if (consp r1) (car r1) r1) + r1-max (if (consp r1) (cdr r1) r1))) + ((and (<= r2-min r1-min) (<= r2-max r1-max)) ; r2 overlap min r1 + (pop range2) + (setq r1-min (1+ r2-max) + r2 (car range2) + r2-min (if (consp r2) (car r2) r2) + r2-max (if (consp r2) (cdr r2) r2))) + ((and (<= r1-min r2-min) (<= r2-max r1-max)) ; r2 contained in r1 + (if (eq r1-min (1- r2-min)) + (push r1-min out) + (push (cons r1-min (1- r2-min)) out)) + (pop range2) + (if (< r2-max r1-max) ; finished with r1? + (setq r1-min (1+ r2-max)) + (pop range1) + (setq r1 (car range1) + r1-min (if (consp r1) (car r1) r1) + r1-max (if (consp r1) (cdr r1) r1))) + (setq r2 (car range2) + r2-min (if (consp r2) (car r2) r2) + r2-max (if (consp r2) (cdr r2) r2))) + ((and (<= r2-min r1-max) (<= r1-max r2-max)) ; r2 overlap max r1 + (if (eq r1-min (1- r2-min)) + (push r1-min out) + (push (cons r1-min (1- r2-min)) out)) + (pop range1) + (setq r1 (car range1) + r1-min (if (consp r1) (car r1) r1) + r1-max (if (consp r1) (cdr r1) r1))) + ((< r1-max r2-min) ; r2 > r1 + (pop range1) + (if (eq r1-min r1-max) + (push r1-min out) + (push (cons r1-min r1-max) out)) + (setq r1 (car range1) + r1-min (if (consp r1) (car r1) r1) + r1-max (if (consp r1) (cdr r1) r1))))) + (when r1 + (if (eq r1-min r1-max) + (push r1-min out) + (push (cons r1-min r1-max) out)) + (pop range1)) + (while range1 + (push (pop range1) out)) + (nreverse out)))) + +(defun range-member-p (number ranges) + "Say whether NUMBER is in RANGES." + (if (not (listp (cdr ranges))) + (and (>= number (car ranges)) + (<= number (cdr ranges))) + (let ((not-stop t)) + (while (and ranges + (if (numberp (car ranges)) + (>= number (car ranges)) + (>= number (caar ranges))) + not-stop) + (when (if (numberp (car ranges)) + (= number (car ranges)) + (and (>= number (caar ranges)) + (<= number (cdar ranges)))) + (setq not-stop nil)) + (setq ranges (cdr ranges))) + (not not-stop)))) + +(defun range-list-intersection (list ranges) + "Return a list of numbers in LIST that are members of RANGES. +oLIST is a sorted list." + (setq ranges (range-normalize ranges)) + (let (number result) + (while (setq number (pop list)) + (while (and ranges + (if (numberp (car ranges)) + (< (car ranges) number) + (< (cdar ranges) number))) + (setq ranges (cdr ranges))) + (when (and ranges + (if (numberp (car ranges)) + (= (car ranges) number) + ;; (caar ranges) <= number <= (cdar ranges) + (>= number (caar ranges)))) + (push number result))) + (nreverse result))) + +(defun range-list-difference (list ranges) + "Return a list of numbers in LIST that are not members of RANGES. +LIST is a sorted list." + (setq ranges (range-normalize ranges)) + (let (number result) + (while (setq number (pop list)) + (while (and ranges + (if (numberp (car ranges)) + (< (car ranges) number) + (< (cdar ranges) number))) + (setq ranges (cdr ranges))) + (when (or (not ranges) + (if (numberp (car ranges)) + (not (= (car ranges) number)) + ;; not ((caar ranges) <= number <= (cdar ranges)) + (< number (caar ranges)))) + (push number result))) + (nreverse result))) + +(defun range-length (range) + "Return the length RANGE would have if uncompressed." + (cond + ((null range) + 0) + ((not (listp (cdr range))) + (- (cdr range) (car range) -1)) + (t + (let ((sum 0)) + (dolist (x range sum) + (setq sum + (+ sum (if (consp x) (- (cdr x) (car x) -1) 1)))))))) + +(defun range-concat (range1 range2) + "Add RANGE2 to RANGE1 (nondestructively)." + (unless (listp (cdr range1)) + (setq range1 (list range1))) + (unless (listp (cdr range2)) + (setq range2 (list range2))) + (let ((item1 (pop range1)) + (item2 (pop range2)) + range item selector) + (while (or item1 item2) + (setq selector + (cond + ((null item1) nil) + ((null item2) t) + ((and (numberp item1) (numberp item2)) (< item1 item2)) + ((numberp item1) (< item1 (car item2))) + ((numberp item2) (< (car item1) item2)) + (t (< (car item1) (car item2))))) + (setq item + (or + (let ((tmp1 item) (tmp2 (if selector item1 item2))) + (cond + ((null tmp1) tmp2) + ((null tmp2) tmp1) + ((and (numberp tmp1) (numberp tmp2)) + (cond + ((eq tmp1 tmp2) tmp1) + ((eq (1+ tmp1) tmp2) (cons tmp1 tmp2)) + ((eq (1+ tmp2) tmp1) (cons tmp2 tmp1)) + (t nil))) + ((numberp tmp1) + (cond + ((and (>= tmp1 (car tmp2)) (<= tmp1 (cdr tmp2))) tmp2) + ((eq (1+ tmp1) (car tmp2)) (cons tmp1 (cdr tmp2))) + ((eq (1- tmp1) (cdr tmp2)) (cons (car tmp2) tmp1)) + (t nil))) + ((numberp tmp2) + (cond + ((and (>= tmp2 (car tmp1)) (<= tmp2 (cdr tmp1))) tmp1) + ((eq (1+ tmp2) (car tmp1)) (cons tmp2 (cdr tmp1))) + ((eq (1- tmp2) (cdr tmp1)) (cons (car tmp1) tmp2)) + (t nil))) + ((< (1+ (cdr tmp1)) (car tmp2)) nil) + ((< (1+ (cdr tmp2)) (car tmp1)) nil) + (t (cons (min (car tmp1) (car tmp2)) + (max (cdr tmp1) (cdr tmp2)))))) + (progn + (if item (push item range)) + (if selector item1 item2)))) + (if selector + (setq item1 (pop range1)) + (setq item2 (pop range2)))) + (if item (push item range)) + (reverse range))) + +(defun range-map (func range) + "Apply FUNC to each value contained by RANGE." + (setq range (range-normalize range)) + (while range + (let ((span (pop range))) + (if (numberp span) + (funcall func span) + (let ((first (car span)) + (last (cdr span))) + (while (<= first last) + (funcall func first) + (setq first (1+ first)))))))) + +(provide 'range) + +;;; range.el ends here diff --git a/lisp/gnus/gnus-agent.el b/lisp/gnus/gnus-agent.el index fd66135b5c6..e4704b35c8d 100644 --- a/lisp/gnus/gnus-agent.el +++ b/lisp/gnus/gnus-agent.el @@ -31,6 +31,7 @@ (require 'gnus-srvr) (require 'gnus-util) (require 'timer) +(require 'range) (eval-when-compile (require 'cl-lib)) (autoload 'gnus-server-update-server "gnus-srvr") @@ -1219,8 +1220,8 @@ This can be added to `gnus-select-article-hook' or (cond ((eq mark 'read) (setf (gnus-info-read info) (funcall (if (eq what 'add) - #'gnus-range-add - #'gnus-remove-from-range) + #'range-concat + #'range-remove) (gnus-info-read info) range)) (gnus-get-unread-articles-in-group @@ -1233,8 +1234,8 @@ This can be added to `gnus-select-article-hook' or (gnus-info-marks info))) (setcdr info-marks (funcall (if (eq what 'add) - #'gnus-range-add - #'gnus-remove-from-range) + #'range-concat + #'range-remove) (cdr info-marks) range)))))))) @@ -1307,7 +1308,7 @@ downloaded into the agent." (let ((read (gnus-info-read info))) (setf (gnus-info-read info) - (gnus-range-add + (range-concat read (list (cons (1+ agent-max) (1- active-min)))))) @@ -1796,13 +1797,13 @@ article numbers will be returned." (articles (if fetch-all (if gnus-newsgroup-maximum-articles (let ((active (gnus-active group))) - (gnus-uncompress-range + (range-uncompress (cons (max (car active) (- (cdr active) gnus-newsgroup-maximum-articles -1)) (cdr active)))) - (gnus-uncompress-range (gnus-active group))) + (range-uncompress (gnus-active group))) (gnus-list-of-unread-articles group))) (gnus-decode-encoded-word-function 'identity) (gnus-decode-encoded-address-function 'identity) @@ -1817,7 +1818,7 @@ article numbers will be returned." ;; because otherwise the agent will remove their marks.) (dolist (arts (gnus-info-marks (gnus-get-info group))) (unless (memq (car arts) '(seen recent killed cache)) - (setq articles (gnus-range-add articles (cdr arts))))) + (setq articles (range-concat articles (cdr arts))))) (setq articles (sort (gnus-uncompress-sequence articles) #'<))) ;; At this point, I have the list of articles to consider for @@ -1851,15 +1852,15 @@ article numbers will be returned." ;; gnus-agent-article-alist) equals (cdr (gnus-active ;; group))}. The addition of one(the 1+ above) then ;; forces Low to be greater than High. When this happens, - ;; gnus-list-range-intersection returns nil which + ;; range-list-intersection returns nil which ;; indicates that no headers need to be fetched. -- Kevin - (setq articles (gnus-list-range-intersection + (setq articles (range-list-intersection articles (list (cons low high))))))) (when articles (gnus-message 10 "gnus-agent-fetch-headers: undownloaded articles are `%s'" - (gnus-compress-sequence articles t))) + (range-compress-list articles))) (with-current-buffer nntp-server-buffer (if articles @@ -2060,7 +2061,7 @@ doesn't exist, to valid the overview buffer." (let (state sequence uncomp) (while alist (setq state (caar alist) - sequence (inline (gnus-uncompress-range (cdar alist))) + sequence (inline (range-uncompress (cdar alist))) alist (cdr alist)) (while sequence (push (cons (pop sequence) state) uncomp))) @@ -2404,7 +2405,7 @@ contents, they are first saved to their own file." (let ((arts (cdr (assq mark (gnus-info-marks (setq info (gnus-get-info group))))))) (when arts - (setq marked-articles (nconc (gnus-uncompress-range arts) + (setq marked-articles (nconc (range-uncompress arts) marked-articles)) )))) (setq marked-articles (sort marked-articles #'<)) @@ -2544,7 +2545,7 @@ contents, they are first saved to their own file." (let ((read (gnus-info-read (or info (setq info (gnus-get-info group)))))) (setf (gnus-info-read info) - (gnus-add-to-range read unfetched-articles))) + (range-add-list read unfetched-articles))) (gnus-group-update-group group t) (sit-for 0) @@ -2898,8 +2899,8 @@ The following commands are available: (defun gnus-agent-read-p () "Say whether an article is read or not." - (gnus-member-of-range (mail-header-number gnus-headers) - (gnus-info-read (gnus-get-info gnus-newsgroup-name)))) + (range-member-p (mail-header-number gnus-headers) + (gnus-info-read (gnus-get-info gnus-newsgroup-name)))) (defun gnus-category-make-function (predicate) "Make a function from PREDICATE." @@ -3115,7 +3116,7 @@ FORCE is equivalent to setting the expiration predicates to true." ;; All articles EXCEPT those named by the caller ;; are protected from expiration (gnus-sorted-difference - (gnus-uncompress-range + (range-uncompress (cons (caar alist) (caar (last alist)))) (sort articles #'<))))) @@ -3137,9 +3138,9 @@ FORCE is equivalent to setting the expiration predicates to true." ;; Ticked and/or dormant articles are excluded ;; from expiration (nconc - (gnus-uncompress-range + (range-uncompress (cdr (assq 'tick (gnus-info-marks info)))) - (gnus-uncompress-range + (range-uncompress (cdr (assq 'dormant (gnus-info-marks info)))))))) (nov-file (concat dir ".overview")) @@ -3638,7 +3639,7 @@ has been fetched." (file-name-directory file) t)) (when fetch-old - (setq articles (gnus-uncompress-range + (setq articles (range-uncompress (cons (if (numberp fetch-old) (max 1 (- (car articles) fetch-old)) 1) @@ -3694,7 +3695,7 @@ has been fetched." ;; Clip this list to the headers that will ;; actually be returned - (setq fetched-articles (gnus-list-range-intersection + (setq fetched-articles (range-list-intersection (cdr fetched-articles) (cons min max))) @@ -3703,7 +3704,7 @@ has been fetched." ;; excluded IDs may be fetchable using HEAD. (if (car tail-fetched-articles) (setq uncached-articles - (gnus-list-range-intersection + (range-list-intersection uncached-articles (cons (car uncached-articles) (car tail-fetched-articles))))) diff --git a/lisp/gnus/gnus-art.el b/lisp/gnus/gnus-art.el index a286c446724..d35d3bdd3a3 100644 --- a/lisp/gnus/gnus-art.el +++ b/lisp/gnus/gnus-art.el @@ -42,6 +42,7 @@ (require 'message) (require 'mouse) (require 'seq) +(require 'range) (autoload 'gnus-msg-mail "gnus-msg" nil t) (autoload 'gnus-button-mailto "gnus-msg") @@ -7019,7 +7020,7 @@ then we display only bindings that start with that prefix." (setq sumkeys (append (mapcar #'vector - (nreverse (gnus-uncompress-range def))) + (nreverse (range-uncompress def))) sumkeys)))) ((setq def (key-binding key)) (unless (eq def 'undefined) diff --git a/lisp/gnus/gnus-cloud.el b/lisp/gnus/gnus-cloud.el index 6ed9e32c919..9bd9f2155f7 100644 --- a/lisp/gnus/gnus-cloud.el +++ b/lisp/gnus/gnus-cloud.el @@ -30,6 +30,7 @@ (require 'parse-time) (require 'nnimap) +(require 'range) (eval-when-compile (require 'epg)) ;; setf-method for `epg-context-armor' (autoload 'epg-make-context "epg") @@ -404,7 +405,7 @@ When FULL is t, upload everything, not just a difference from the last full." (let* ((group (gnus-group-full-name gnus-cloud-group-name gnus-cloud-method)) (active (gnus-active group)) headers head) - (when (gnus-retrieve-headers (gnus-uncompress-range active) group) + (when (gnus-retrieve-headers (range-uncompress active) group) (with-current-buffer nntp-server-buffer (goto-char (point-min)) (while (setq head (nnheader-parse-head)) diff --git a/lisp/gnus/gnus-draft.el b/lisp/gnus/gnus-draft.el index cd9b025ff0e..56d498cc4d3 100644 --- a/lisp/gnus/gnus-draft.el +++ b/lisp/gnus/gnus-draft.el @@ -200,7 +200,7 @@ Obeys the standard process/prefix convention." (gnus-activate-group "nndraft:queue") (save-excursion (let* ((articles (nndraft-articles)) - (unsendable (gnus-uncompress-range + (unsendable (range-uncompress (cdr (assq 'unsend (gnus-info-marks (gnus-get-info "nndraft:queue")))))) diff --git a/lisp/gnus/gnus-group.el b/lisp/gnus/gnus-group.el index ab874dd0608..d3a94e9f4e0 100644 --- a/lisp/gnus/gnus-group.el +++ b/lisp/gnus/gnus-group.el @@ -35,6 +35,7 @@ (require 'gnus-undo) (require 'gmm-utils) (require 'time-date) +(require 'range) (eval-when-compile (require 'mm-url) @@ -512,8 +513,8 @@ simple manner." ((numberp number) (int-to-string (+ number - (gnus-range-length (cdr (assq 'dormant gnus-tmp-marked))) - (gnus-range-length (cdr (assq 'tick gnus-tmp-marked)))))) + (range-length (cdr (assq 'dormant gnus-tmp-marked))) + (range-length (cdr (assq 'tick gnus-tmp-marked)))))) (t number)) ?s) (?R gnus-tmp-number-of-read ?s) @@ -523,10 +524,10 @@ simple manner." ?s) (?t gnus-tmp-number-total ?d) (?y gnus-tmp-number-of-unread ?s) - (?I (gnus-range-length (cdr (assq 'dormant gnus-tmp-marked))) ?d) - (?T (gnus-range-length (cdr (assq 'tick gnus-tmp-marked))) ?d) - (?i (+ (gnus-range-length (cdr (assq 'dormant gnus-tmp-marked))) - (gnus-range-length (cdr (assq 'tick gnus-tmp-marked)))) + (?I (range-length (cdr (assq 'dormant gnus-tmp-marked))) ?d) + (?T (range-length (cdr (assq 'tick gnus-tmp-marked))) ?d) + (?i (+ (range-length (cdr (assq 'dormant gnus-tmp-marked))) + (range-length (cdr (assq 'tick gnus-tmp-marked)))) ?d) (?g gnus-tmp-group ?s) (?G gnus-tmp-qualified-group ?s) @@ -1482,9 +1483,9 @@ if it is a string, only list groups matching REGEXP." (active (gnus-active group))) (if (not active) 0 - (length (gnus-uncompress-range - (gnus-range-difference - (gnus-range-difference (list active) (gnus-info-read info)) + (length (range-uncompress + (range-difference + (range-difference (list active) (gnus-info-read info)) seen)))))) ;; Moving through the Group buffer (in topic mode) e.g. with C-n doesn't @@ -1642,7 +1643,7 @@ Some value are bound so the form can use them." '(mail post-mail)))) (cons 'level (or (gnus-info-level info) gnus-level-killed)) (cons 'score (or (gnus-info-score info) 0)) - (cons 'ticked (gnus-range-length (cdr (assq 'tick marked)))) + (cons 'ticked (range-length (cdr (assq 'tick marked)))) (cons 'group-age (gnus-group-timestamp-delta group))))) (while (and list (not (eval (caar list) env))) @@ -2065,9 +2066,9 @@ that group." (- (1+ (cdr active)) (car active))))) (gnus-summary-read-group group (or all (and (numberp number) - (zerop (+ number (gnus-range-length + (zerop (+ number (range-length (cdr (assq 'tick marked))) - (gnus-range-length + (range-length (cdr (assq 'dormant marked))))))) no-article nil no-display nil select-articles))) @@ -2832,7 +2833,7 @@ according to the expiry settings. Note that this will delete old not-expirable articles, too." (interactive (list (gnus-group-group-name) current-prefix-arg) gnus-group-mode) - (let ((articles (gnus-uncompress-range (gnus-active group)))) + (let ((articles (range-uncompress (gnus-active group)))) (when (gnus-yes-or-no-p (format "Do you really want to delete these %d articles forever? " (length articles))) @@ -3755,15 +3756,15 @@ or nil if no action could be taken." 'del '(tick)) (list (cdr (assq 'dormant marks)) 'del '(dormant)))) - (setq unread (gnus-range-add (gnus-range-add - unread (cdr (assq 'dormant marks))) - (cdr (assq 'tick marks)))) + (setq unread (range-concat (range-concat + unread (cdr (assq 'dormant marks))) + (cdr (assq 'tick marks)))) (gnus-add-marked-articles group 'tick nil nil 'force) (gnus-add-marked-articles group 'dormant nil nil 'force)) ;; Do auto-expirable marks if that's required. (when (and (gnus-group-auto-expirable-p group) (not (gnus-group-read-only-p group))) - (gnus-range-map + (range-map (lambda (article) (gnus-add-marked-articles group 'expire (list article)) (gnus-request-set-mark group (list (list (list article) @@ -3795,7 +3796,7 @@ Uses the process/prefix convention." (cons nil (gnus-list-of-read-articles group)) (assq 'expire (gnus-info-marks info)))) (articles-to-expire - (gnus-list-range-difference + (range-list-difference (gnus-uncompress-sequence (cdr expirable)) (cdr (assq 'unexist (gnus-info-marks info))))) (expiry-wait (gnus-group-find-parameter group 'expiry-wait)) @@ -4671,23 +4672,22 @@ and the second element is the address." (and (not (setq marked (nthcdr 3 info))) (or (null articles) (setcdr (nthcdr 2 info) - (list (list (cons type (gnus-compress-sequence - articles t))))))) + (list (list (cons type (range-compress-list + articles))))))) (and (not (setq m (assq type (car marked)))) (or (null articles) (setcar marked - (cons (cons type (gnus-compress-sequence articles t) ) + (cons (cons type (range-compress-list articles)) (car marked))))) (if force (if (null articles) (setcar (nthcdr 3 info) (assq-delete-all type (car marked))) - (setcdr m (gnus-compress-sequence articles t))) - (setcdr m (gnus-compress-sequence - (sort (nconc (gnus-uncompress-range (cdr m)) + (setcdr m (range-compress-list articles))) + (setcdr m (range-compress-list + (sort (nconc (range-uncompress (cdr m)) (copy-sequence articles)) - #'<) - t)))))) + #'<))))))) (declare-function gnus-summary-add-mark "gnus-sum" (article type)) diff --git a/lisp/gnus/gnus-int.el b/lisp/gnus/gnus-int.el index 5a619e8f07b..f00f2a0d04e 100644 --- a/lisp/gnus/gnus-int.el +++ b/lisp/gnus/gnus-int.el @@ -802,7 +802,7 @@ If GROUP is nil, all groups on COMMAND-METHOD are scanned." (when (> min 1) (let* ((range (if (= min 2) 1 (cons 1 (1- min)))) (read (gnus-info-read info)) - (new-read (gnus-range-add read (list range)))) + (new-read (range-concat read (list range)))) (setf (gnus-info-read info) new-read))) info)))))) diff --git a/lisp/gnus/gnus-kill.el b/lisp/gnus/gnus-kill.el index bee7860efdb..bc49f8385ea 100644 --- a/lisp/gnus/gnus-kill.el +++ b/lisp/gnus/gnus-kill.el @@ -349,7 +349,7 @@ Returns the number of articles marked as read." (setq gnus-newsgroup-kill-headers (mapcar #'mail-header-number headers)) (while headers - (unless (gnus-member-of-range + (unless (range-member-p (mail-header-number (car headers)) gnus-newsgroup-killed) (push (mail-header-number (car headers)) diff --git a/lisp/gnus/gnus-range.el b/lisp/gnus/gnus-range.el index da3ff473725..23a71bda209 100644 --- a/lisp/gnus/gnus-range.el +++ b/lisp/gnus/gnus-range.el @@ -26,10 +26,8 @@ ;;; List and range functions -(defsubst gnus-range-normalize (range) - "Normalize RANGE. -If RANGE is a single range, return (RANGE). Otherwise, return RANGE." - (if (listp (cdr-safe range)) range (list range))) +(require 'range) +(define-obsolete-function-alias 'gnus-range-normalize #'range-normalize "29.1") (defun gnus-last-element (list) "Return last element of LIST." @@ -56,10 +54,10 @@ If RANGE is a single range, return (RANGE). Otherwise, return RANGE." "Return a range comprising all the RANGES, which are pre-sorted. RANGES will be destructively altered." (setq ranges (delete nil ranges)) - (let* ((result (gnus-range-normalize (pop ranges))) + (let* ((result (range-normalize (pop ranges))) (last (last result))) (dolist (range ranges) - (setq range (gnus-range-normalize range)) + (setq range (range-normalize range)) ;; Normalize the single-number case, so that we don't need to ;; special-case that so much. (when (numberp (car last)) @@ -82,47 +80,8 @@ RANGES will be destructively altered." (car result) result))) -(defun gnus-range-difference (range1 range2) - "Return the range of elements in RANGE1 that do not appear in RANGE2. -Both ranges must be in ascending order." - (setq range1 (gnus-range-normalize range1)) - (setq range2 (gnus-range-normalize range2)) - (let* ((new-range (cons nil (copy-sequence range1))) - (r new-range) - ) ;; (safe t) - (while (cdr r) - (let* ((r1 (cadr r)) - (r2 (car range2)) - (min1 (if (numberp r1) r1 (car r1))) - (max1 (if (numberp r1) r1 (cdr r1))) - (min2 (if (numberp r2) r2 (car r2))) - (max2 (if (numberp r2) r2 (cdr r2)))) - - (cond ((> min1 max1) - ;; Invalid range: may result from overlap condition (below) - ;; remove Invalid range - (setcdr r (cddr r))) - ((and (= min1 max1) - (listp r1)) - ;; Inefficient representation: may result from overlap condition (below) - (setcar (cdr r) min1)) - ((not min2) - ;; All done with range2 - (setq r nil)) - ((< max1 min2) - ;; No overlap: range1 precedes range2 - (pop r)) - ((< max2 min1) - ;; No overlap: range2 precedes range1 - (pop range2)) - ((and (<= min2 min1) (<= max1 max2)) - ;; Complete overlap: range1 removed - (setcdr r (cddr r))) - (t - (setcdr r (nconc (list (cons min1 (1- min2)) (cons (1+ max2) max1)) (cddr r))))))) - (cdr new-range))) - - +(define-obsolete-function-alias 'gnus-range-difference + #'range-difference "29.1") ;;;###autoload (defun gnus-sorted-difference (list1 list2) @@ -200,57 +159,8 @@ LIST1 and LIST2 have to be sorted over <." (setq list2 (cdr list2))))) (nreverse out))) -;;;###autoload -(defun gnus-sorted-range-intersection (range1 range2) - "Return intersection of RANGE1 and RANGE2. -RANGE1 and RANGE2 have to be sorted over <." - (let* (out - (min1 (car range1)) - (max1 (if (numberp min1) - (if (numberp (cdr range1)) - (prog1 (cdr range1) - (setq range1 nil)) min1) - (prog1 (cdr min1) - (setq min1 (car min1))))) - (min2 (car range2)) - (max2 (if (numberp min2) - (if (numberp (cdr range2)) - (prog1 (cdr range2) - (setq range2 nil)) min2) - (prog1 (cdr min2) - (setq min2 (car min2)))))) - (setq range1 (cdr range1) - range2 (cdr range2)) - (while (and min1 min2) - (cond ((< max1 min2) ; range1 precedes range2 - (setq range1 (cdr range1) - min1 nil)) - ((< max2 min1) ; range2 precedes range1 - (setq range2 (cdr range2) - min2 nil)) - (t ; some sort of overlap is occurring - (let ((min (max min1 min2)) - (max (min max1 max2))) - (setq out (if (= min max) - (cons min out) - (cons (cons min max) out)))) - (if (< max1 max2) ; range1 ends before range2 - (setq min1 nil) ; incr range1 - (setq min2 nil)))) ; incr range2 - (unless min1 - (setq min1 (car range1) - max1 (if (numberp min1) min1 (prog1 (cdr min1) (setq min1 (car min1)))) - range1 (cdr range1))) - (unless min2 - (setq min2 (car range2) - max2 (if (numberp min2) min2 (prog1 (cdr min2) (setq min2 (car min2)))) - range2 (cdr range2)))) - (cond ((cdr out) - (nreverse out)) - ((numberp (car out)) - out) - (t - (car out))))) +(define-obsolete-function-alias 'gnus-sorted-range-intersection + #'range-intersection "29.1") ;;;###autoload (defalias 'gnus-set-sorted-intersection 'gnus-sorted-nintersection) @@ -327,315 +237,33 @@ LIST1 and LIST2 have to be sorted over <." "Convert sorted list of numbers to a list of ranges or a single range. If ALWAYS-LIST is non-nil, this function will always release a list of ranges." - (let* ((first (car numbers)) - (last (car numbers)) - result) - (if (null numbers) - nil - (if (not (listp (cdr numbers))) - numbers - (while numbers - (cond ((= last (car numbers)) nil) ;Omit duplicated number - ((= (1+ last) (car numbers)) ;Still in sequence - (setq last (car numbers))) - (t ;End of one sequence - (setq result - (cons (if (= first last) first - (cons first last)) - result)) - (setq first (car numbers)) - (setq last (car numbers)))) - (setq numbers (cdr numbers))) - (if (and (not always-list) (null result)) - (if (= first last) (list first) (cons first last)) - (nreverse (cons (if (= first last) first (cons first last)) - result))))))) + (if always-list + (range-compress-list numbers) + (range-denormalize (range-compress-list numbers)))) (defalias 'gnus-uncompress-sequence 'gnus-uncompress-range) -(defun gnus-uncompress-range (ranges) - "Expand a list of ranges into a list of numbers. -RANGES is either a single range on the form `(num . num)' or a list of -these ranges." - (let (first last result) - (cond - ((null ranges) - nil) - ((not (listp (cdr ranges))) - (setq first (car ranges)) - (setq last (cdr ranges)) - (while (<= first last) - (setq result (cons first result)) - (setq first (1+ first))) - (nreverse result)) - (t - (while ranges - (if (atom (car ranges)) - (when (numberp (car ranges)) - (setq result (cons (car ranges) result))) - (setq first (caar ranges)) - (setq last (cdar ranges)) - (while (<= first last) - (setq result (cons first result)) - (setq first (1+ first)))) - (setq ranges (cdr ranges))) - (nreverse result))))) - -(defun gnus-add-to-range (ranges list) - "Return a list of ranges that has all articles from both RANGES and LIST. -Note: LIST has to be sorted over `<'." - (if (not ranges) - (gnus-compress-sequence list t) - (setq list (copy-sequence list)) - (unless (listp (cdr ranges)) - (setq ranges (list ranges))) - (let ((out ranges) - ilist lowest highest temp) - (while (and ranges list) - (setq ilist list) - (setq lowest (or (and (atom (car ranges)) (car ranges)) - (caar ranges))) - (while (and list (cdr list) (< (cadr list) lowest)) - (setq list (cdr list))) - (when (< (car ilist) lowest) - (setq temp list) - (setq list (cdr list)) - (setcdr temp nil) - (setq out (nconc (gnus-compress-sequence ilist t) out))) - (setq highest (or (and (atom (car ranges)) (car ranges)) - (cdar ranges))) - (while (and list (<= (car list) highest)) - (setq list (cdr list))) - (setq ranges (cdr ranges))) - (when list - (setq out (nconc (gnus-compress-sequence list t) out))) - (setq out (sort out (lambda (r1 r2) - (< (or (and (atom r1) r1) (car r1)) - (or (and (atom r2) r2) (car r2)))))) - (setq ranges out) - (while ranges - (if (atom (car ranges)) - (when (cdr ranges) - (if (atom (cadr ranges)) - (when (= (1+ (car ranges)) (cadr ranges)) - (setcar ranges (cons (car ranges) - (cadr ranges))) - (setcdr ranges (cddr ranges))) - (when (= (1+ (car ranges)) (caadr ranges)) - (setcar (cadr ranges) (car ranges)) - (setcar ranges (cadr ranges)) - (setcdr ranges (cddr ranges))))) - (when (cdr ranges) - (if (atom (cadr ranges)) - (when (= (1+ (cdar ranges)) (cadr ranges)) - (setcdr (car ranges) (cadr ranges)) - (setcdr ranges (cddr ranges))) - (when (= (1+ (cdar ranges)) (caadr ranges)) - (setcdr (car ranges) (cdadr ranges)) - (setcdr ranges (cddr ranges)))))) - (setq ranges (cdr ranges))) - out))) - -(defun gnus-remove-from-range (range1 range2) - "Return a range that has all articles from RANGE2 removed from RANGE1. -The returned range is always a list. RANGE2 can also be a unsorted -list of articles. RANGE1 is modified by side effects, RANGE2 is not -modified." - (if (or (null range1) (null range2)) - range1 - (let (out r1 r2 r1_min r1_max r2_min r2_max - (range2 (copy-tree range2))) - (setq range1 (if (listp (cdr range1)) range1 (list range1)) - range2 (sort (if (listp (cdr range2)) range2 (list range2)) - (lambda (e1 e2) - (< (if (consp e1) (car e1) e1) - (if (consp e2) (car e2) e2)))) - r1 (car range1) - r2 (car range2) - r1_min (if (consp r1) (car r1) r1) - r1_max (if (consp r1) (cdr r1) r1) - r2_min (if (consp r2) (car r2) r2) - r2_max (if (consp r2) (cdr r2) r2)) - (while (and range1 range2) - (cond ((< r2_max r1_min) ; r2 < r1 - (pop range2) - (setq r2 (car range2) - r2_min (if (consp r2) (car r2) r2) - r2_max (if (consp r2) (cdr r2) r2))) - ((and (<= r2_min r1_min) (<= r1_max r2_max)) ; r2 overlap r1 - (pop range1) - (setq r1 (car range1) - r1_min (if (consp r1) (car r1) r1) - r1_max (if (consp r1) (cdr r1) r1))) - ((and (<= r2_min r1_min) (<= r2_max r1_max)) ; r2 overlap min r1 - (pop range2) - (setq r1_min (1+ r2_max) - r2 (car range2) - r2_min (if (consp r2) (car r2) r2) - r2_max (if (consp r2) (cdr r2) r2))) - ((and (<= r1_min r2_min) (<= r2_max r1_max)) ; r2 contained in r1 - (if (eq r1_min (1- r2_min)) - (push r1_min out) - (push (cons r1_min (1- r2_min)) out)) - (pop range2) - (if (< r2_max r1_max) ; finished with r1? - (setq r1_min (1+ r2_max)) - (pop range1) - (setq r1 (car range1) - r1_min (if (consp r1) (car r1) r1) - r1_max (if (consp r1) (cdr r1) r1))) - (setq r2 (car range2) - r2_min (if (consp r2) (car r2) r2) - r2_max (if (consp r2) (cdr r2) r2))) - ((and (<= r2_min r1_max) (<= r1_max r2_max)) ; r2 overlap max r1 - (if (eq r1_min (1- r2_min)) - (push r1_min out) - (push (cons r1_min (1- r2_min)) out)) - (pop range1) - (setq r1 (car range1) - r1_min (if (consp r1) (car r1) r1) - r1_max (if (consp r1) (cdr r1) r1))) - ((< r1_max r2_min) ; r2 > r1 - (pop range1) - (if (eq r1_min r1_max) - (push r1_min out) - (push (cons r1_min r1_max) out)) - (setq r1 (car range1) - r1_min (if (consp r1) (car r1) r1) - r1_max (if (consp r1) (cdr r1) r1))))) - (when r1 - (if (eq r1_min r1_max) - (push r1_min out) - (push (cons r1_min r1_max) out)) - (pop range1)) - (while range1 - (push (pop range1) out)) - (nreverse out)))) - -(defun gnus-member-of-range (number ranges) - (if (not (listp (cdr ranges))) - (and (>= number (car ranges)) - (<= number (cdr ranges))) - (let ((not-stop t)) - (while (and ranges - (if (numberp (car ranges)) - (>= number (car ranges)) - (>= number (caar ranges))) - not-stop) - (when (if (numberp (car ranges)) - (= number (car ranges)) - (and (>= number (caar ranges)) - (<= number (cdar ranges)))) - (setq not-stop nil)) - (setq ranges (cdr ranges))) - (not not-stop)))) - -(defun gnus-list-range-intersection (list ranges) - "Return a list of numbers in LIST that are members of RANGES. -LIST is a sorted list." - (setq ranges (gnus-range-normalize ranges)) - (let (number result) - (while (setq number (pop list)) - (while (and ranges - (if (numberp (car ranges)) - (< (car ranges) number) - (< (cdar ranges) number))) - (setq ranges (cdr ranges))) - (when (and ranges - (if (numberp (car ranges)) - (= (car ranges) number) - ;; (caar ranges) <= number <= (cdar ranges) - (>= number (caar ranges)))) - (push number result))) - (nreverse result))) +(define-obsolete-function-alias 'gnus-uncompress-range + #'range-uncompress "29.1") + +(define-obsolete-function-alias 'gnus-add-to-range + #'range-add-list "29.1") + +(define-obsolete-function-alias 'gnus-remove-from-range + #'range-remove "29.1") + +(define-obsolete-function-alias 'gnus-member-of-range #'range-member-p "29.1") + +(define-obsolete-function-alias 'gnus-list-range-intersection + #'range-list-intersection "29.1") (defalias 'gnus-inverse-list-range-intersection 'gnus-list-range-difference) -(defun gnus-list-range-difference (list ranges) - "Return a list of numbers in LIST that are not members of RANGES. -LIST is a sorted list." - (setq ranges (gnus-range-normalize ranges)) - (let (number result) - (while (setq number (pop list)) - (while (and ranges - (if (numberp (car ranges)) - (< (car ranges) number) - (< (cdar ranges) number))) - (setq ranges (cdr ranges))) - (when (or (not ranges) - (if (numberp (car ranges)) - (not (= (car ranges) number)) - ;; not ((caar ranges) <= number <= (cdar ranges)) - (< number (caar ranges)))) - (push number result))) - (nreverse result))) +(define-obsolete-function-alias 'gnus-list-range-difference + #'range-list-difference "29.1") + +(define-obsolete-function-alias 'gnus-range-length #'range-length "29.1") -(defun gnus-range-length (range) - "Return the length RANGE would have if uncompressed." - (cond - ((null range) - 0) - ((not (listp (cdr range))) - (- (cdr range) (car range) -1)) - (t - (let ((sum 0)) - (dolist (x range sum) - (setq sum - (+ sum (if (consp x) (- (cdr x) (car x) -1) 1)))))))) - -(defun gnus-range-add (range1 range2) - "Add RANGE2 to RANGE1 (nondestructively)." - (unless (listp (cdr range1)) - (setq range1 (list range1))) - (unless (listp (cdr range2)) - (setq range2 (list range2))) - (let ((item1 (pop range1)) - (item2 (pop range2)) - range item selector) - (while (or item1 item2) - (setq selector - (cond - ((null item1) nil) - ((null item2) t) - ((and (numberp item1) (numberp item2)) (< item1 item2)) - ((numberp item1) (< item1 (car item2))) - ((numberp item2) (< (car item1) item2)) - (t (< (car item1) (car item2))))) - (setq item - (or - (let ((tmp1 item) (tmp2 (if selector item1 item2))) - (cond - ((null tmp1) tmp2) - ((null tmp2) tmp1) - ((and (numberp tmp1) (numberp tmp2)) - (cond - ((eq tmp1 tmp2) tmp1) - ((eq (1+ tmp1) tmp2) (cons tmp1 tmp2)) - ((eq (1+ tmp2) tmp1) (cons tmp2 tmp1)) - (t nil))) - ((numberp tmp1) - (cond - ((and (>= tmp1 (car tmp2)) (<= tmp1 (cdr tmp2))) tmp2) - ((eq (1+ tmp1) (car tmp2)) (cons tmp1 (cdr tmp2))) - ((eq (1- tmp1) (cdr tmp2)) (cons (car tmp2) tmp1)) - (t nil))) - ((numberp tmp2) - (cond - ((and (>= tmp2 (car tmp1)) (<= tmp2 (cdr tmp1))) tmp1) - ((eq (1+ tmp2) (car tmp1)) (cons tmp2 (cdr tmp1))) - ((eq (1- tmp2) (cdr tmp1)) (cons (car tmp1) tmp2)) - (t nil))) - ((< (1+ (cdr tmp1)) (car tmp2)) nil) - ((< (1+ (cdr tmp2)) (car tmp1)) nil) - (t (cons (min (car tmp1) (car tmp2)) - (max (cdr tmp1) (cdr tmp2)))))) - (progn - (if item (push item range)) - (if selector item1 item2)))) - (if selector - (setq item1 (pop range1)) - (setq item2 (pop range2)))) - (if item (push item range)) - (reverse range))) +(define-obsolete-function-alias 'gnus-range-add #'range-concat "29.1") ;;;###autoload (defun gnus-add-to-sorted-list (list num) @@ -649,18 +277,7 @@ LIST is a sorted list." (setcdr prev (cons num list))) (cdr top))) -(defun gnus-range-map (func range) - "Apply FUNC to each value contained by RANGE." - (setq range (gnus-range-normalize range)) - (while range - (let ((span (pop range))) - (if (numberp span) - (funcall func span) - (let ((first (car span)) - (last (cdr span))) - (while (<= first last) - (funcall func first) - (setq first (1+ first)))))))) +(define-obsolete-function-alias 'gnus-range-map #'range-map "29.1") (provide 'gnus-range) diff --git a/lisp/gnus/gnus-start.el b/lisp/gnus/gnus-start.el index 252e6e22299..2cf11fb12f9 100644 --- a/lisp/gnus/gnus-start.el +++ b/lisp/gnus/gnus-start.el @@ -1884,13 +1884,12 @@ The info element is shared with the same element of (ranges (gnus-info-read info)) news article) (while articles - (when (gnus-member-of-range - (setq article (pop articles)) ranges) + (when (range-member-p (setq article (pop articles)) ranges) (push article news))) (when news ;; Enter this list into the group info. (setf (gnus-info-read info) - (gnus-remove-from-range (gnus-info-read info) (nreverse news))) + (range-remove (gnus-info-read info) (nreverse news))) ;; Set the number of unread articles in gnus-newsrc-hashtb. (gnus-get-unread-articles-in-group info (gnus-active group)) @@ -2362,10 +2361,10 @@ The form should return either t or nil." ticked (cdr (assq 'tick marks))) (when (or dormant ticked) (setf (gnus-info-read info) - (gnus-add-to-range + (range-add-list (gnus-info-read info) - (nconc (gnus-uncompress-range dormant) - (gnus-uncompress-range ticked))))))))) + (nconc (range-uncompress dormant) + (range-uncompress ticked))))))))) (defun gnus-load (file) "Load FILE, but in such a way that read errors can be reported." @@ -2457,8 +2456,7 @@ The form should return either t or nil." (unless (nthcdr 3 info) (nconc info (list nil))) (setf (gnus-info-marks info) - (list (cons 'tick (gnus-compress-sequence - (sort (cdr m) #'<) t)))))) + (list (cons 'tick (range-compress-list (sort (cdr m) #'<))))))) (setq newsrc killed) (while newsrc (setcar newsrc (caar newsrc)) diff --git a/lisp/gnus/gnus-sum.el b/lisp/gnus/gnus-sum.el index 6dfdcaf55c7..8fb07d5905c 100644 --- a/lisp/gnus/gnus-sum.el +++ b/lisp/gnus/gnus-sum.el @@ -5755,7 +5755,7 @@ If SELECT-ARTICLES, only select those articles from GROUP." ;; (let ((n (cdr (gnus-active group)))) ;; (lambda () (> number (- n display)))) (setq select-articles - (gnus-uncompress-range + (range-uncompress (cons (let ((tmp (- (cdr (gnus-active group)) display))) (if (> tmp 0) tmp @@ -5928,7 +5928,7 @@ If SELECT-ARTICLES, only select those articles from GROUP." "Find out what articles the user wants to read." (let* ((only-read-p t) (articles - (gnus-list-range-difference + (range-list-difference ;; Select all articles if `read-all' is non-nil, or if there ;; are no unread articles. (if (or read-all @@ -5943,13 +5943,13 @@ If SELECT-ARTICLES, only select those articles from GROUP." (or (if gnus-newsgroup-maximum-articles (let ((active (gnus-active group))) - (gnus-uncompress-range + (range-uncompress (cons (max (car active) (- (cdr active) gnus-newsgroup-maximum-articles -1)) (cdr active)))) - (gnus-uncompress-range (gnus-active group))) + (range-uncompress (gnus-active group))) (gnus-cache-articles-in-group group)) ;; Select only the "normal" subset of articles. (setq only-read-p nil) @@ -6040,7 +6040,7 @@ If SELECT-ARTICLES, only select those articles from GROUP." (defun gnus-killed-articles (killed articles) (let (out) (while articles - (when (inline (gnus-member-of-range (car articles) killed)) + (when (inline (range-member-p (car articles) killed)) (push (car articles) out)) (setq articles (cdr articles))) out)) @@ -6078,7 +6078,7 @@ If SELECT-ARTICLES, only select those articles from GROUP." ;; Adjust "simple" lists - compressed yet unsorted ((eq mark-type 'list) ;; Simultaneously uncompress and clip to active range - ;; See gnus-uncompress-range for a description of possible marks + ;; See range-uncompress for a description of possible marks (let (l lh) (if (not (cadr marks)) (set var nil) @@ -6177,10 +6177,10 @@ If SELECT-ARTICLES, only select those articles from GROUP." ;; When exiting the group, everything that's previously been ;; unseen is now seen. (when (eq (cdr type) 'seen) - (setq list (gnus-range-add list gnus-newsgroup-unseen))) + (setq list (range-concat list gnus-newsgroup-unseen))) (when (eq (gnus-article-mark-to-type (cdr type)) 'list) - (setq list (gnus-compress-sequence (set symbol (sort list #'<)) t))) + (setq list (range-compress-list (set symbol (sort list #'<))))) (when (and (gnus-check-backend-function 'request-set-mark gnus-newsgroup-name) @@ -6189,20 +6189,19 @@ If SELECT-ARTICLES, only select those articles from GROUP." ;; Don't do anything about marks for articles we ;; didn't actually get any headers for. (del - (gnus-list-range-intersection + (range-list-intersection gnus-newsgroup-articles - (gnus-remove-from-range (copy-tree old) list))) + (range-remove (copy-tree old) list))) (add - (gnus-list-range-intersection + (range-list-intersection gnus-newsgroup-articles - (gnus-remove-from-range - (copy-tree list) old)))) + (range-remove (copy-tree list) old)))) (when add (push (list add 'add (list (cdr type))) delta-marks)) (when del ;; Don't delete marks from outside the active range. ;; This shouldn't happen, but is a sanity check. - (setq del (gnus-sorted-range-intersection + (setq del (range-intersection (gnus-active gnus-newsgroup-name) del)) (push (list del 'del (list (cdr type))) delta-marks)))) @@ -6386,7 +6385,7 @@ The resulting hash table is returned, or nil if no Xrefs were found." (setq ninfo (cons 1 (1- (car active)))) (setq ninfo (gnus-info-read info))) ;; Then we add the read articles to the range. - (gnus-add-to-range + (range-add-list ninfo (setq articles (sort articles #'<)))))) (defun gnus-group-make-articles-read (group articles) @@ -6967,10 +6966,10 @@ displayed, no centering will be performed." (marked (gnus-info-marks info)) (active (gnus-active group))) (and info active - (gnus-list-range-difference - (gnus-list-range-difference + (range-list-difference + (range-list-difference (gnus-sorted-complement - (gnus-uncompress-range + (range-uncompress (if gnus-newsgroup-maximum-articles (cons (max (car active) (- (cdr active) @@ -7129,12 +7128,11 @@ The prefix argument ALL means to select all articles." (when group (when gnus-newsgroup-kill-headers (setq gnus-newsgroup-killed - (gnus-compress-sequence + (range-compress-list (gnus-sorted-union - (gnus-list-range-intersection + (range-list-intersection gnus-newsgroup-unselected gnus-newsgroup-killed) - gnus-newsgroup-unreads) - t))) + gnus-newsgroup-unreads)))) (unless (listp (cdr gnus-newsgroup-killed)) (setq gnus-newsgroup-killed (list gnus-newsgroup-killed))) (let ((headers gnus-newsgroup-headers) @@ -10241,8 +10239,8 @@ ACTION can be either `move' (the default), `crosspost' or `copy'." (cdr art-group)) (push 'read to-marks) (setf (gnus-info-read info) - (gnus-add-to-range (gnus-info-read info) - (list (cdr art-group))))) + (range-add-list (gnus-info-read info) + (list (cdr art-group))))) ;; See whether the article is to be put in the cache. (let* ((expirable (gnus-group-auto-expirable-p to-group)) @@ -10525,7 +10523,7 @@ This will be the case if the article has both been mailed and posted." ;; This backend supports expiry. (let* ((total (gnus-group-total-expirable-p gnus-newsgroup-name)) (expirable - (gnus-list-range-difference + (range-list-difference (if total (progn ;; We need to update the info for @@ -12874,8 +12872,8 @@ UNREAD is a sorted list." (gnus-find-method-for-group group) 'server-marks) (gnus-check-backend-function 'request-set-mark group)) - (let ((del (gnus-remove-from-range (gnus-info-read info) read)) - (add (gnus-remove-from-range read (gnus-info-read info)))) + (let ((del (range-remove (gnus-info-read info) read)) + (add (range-remove read (gnus-info-read info)))) (when (or add del) (unless (gnus-check-group group) (error "Can't open server for %s" group)) @@ -13133,10 +13131,10 @@ If ALL is a number, fetch this number of articles." ;; Some nntp servers lie about their active range. When ;; this happens, the active range can be in the millions. ;; Use a compressed range to avoid creating a huge list. - (gnus-range-difference - (gnus-range-difference (list gnus-newsgroup-active) old) + (range-difference + (range-difference (list gnus-newsgroup-active) old) gnus-newsgroup-unexist)) - (setq len (gnus-range-length older)) + (setq len (range-length older)) (cond ((null older) nil) ((numberp all) @@ -13153,9 +13151,9 @@ If ALL is a number, fetch this number of articles." (push max older) (setq all (1- all) max (1- max)))))) - (setq older (gnus-uncompress-range older)))) + (setq older (range-uncompress older)))) (all - (setq older (gnus-uncompress-range older))) + (setq older (range-uncompress older))) (t (when (and (numberp gnus-large-newsgroup) (> len gnus-large-newsgroup)) @@ -13190,7 +13188,7 @@ If ALL is a number, fetch this number of articles." (push max older) (setq all (1- all) max (1- max)))))))))) - (setq older (gnus-uncompress-range older)))) + (setq older (range-uncompress older)))) (if (not older) (message "No old news.") (gnus-summary-insert-articles older) diff --git a/lisp/gnus/mail-source.el b/lisp/gnus/mail-source.el index 9a48f710e55..5d0c0e2654b 100644 --- a/lisp/gnus/mail-source.el +++ b/lisp/gnus/mail-source.el @@ -31,6 +31,7 @@ (autoload 'pop3-movemail "pop3") (autoload 'pop3-get-message-count "pop3") (require 'mm-util) +(require 'gnus-range) (require 'message) ;; for `message-directory' (defvar display-time-mail-function) @@ -1048,8 +1049,6 @@ This only works when `display-time' is enabled." (autoload 'imap-range-to-message-set "imap") (autoload 'nnheader-ms-strip-cr "nnheader") -(autoload 'gnus-compress-sequence "gnus-range") - (defvar mail-source-imap-file-coding-system 'binary "Coding system for the crashbox made by `mail-source-fetch-imap'.") diff --git a/lisp/gnus/nnheader.el b/lisp/gnus/nnheader.el index 8b3718ed7e8..c1c5f00ff7f 100644 --- a/lisp/gnus/nnheader.el +++ b/lisp/gnus/nnheader.el @@ -27,6 +27,7 @@ ;;; Code: (eval-when-compile (require 'cl-lib)) +(require 'range) (defvar gnus-decode-encoded-word-function) (defvar gnus-decode-encoded-address-function) @@ -44,8 +45,6 @@ (require 'mm-util) (require 'gnus-util) (autoload 'gnus-remove-odd-characters "gnus-sum") -(autoload 'gnus-range-add "gnus-range") -(autoload 'gnus-remove-from-range "gnus-range") ;; FIXME none of these are used explicitly in this file. (autoload 'gnus-sorted-intersection "gnus-range") (autoload 'gnus-intersection "gnus-range") @@ -1044,10 +1043,9 @@ See `find-file-noselect' for the arguments." mark (cond ((eq what 'add) - (gnus-range-add (cdr (assoc mark backend-marks)) range)) + (range-concat (cdr (assoc mark backend-marks)) range)) ((eq what 'del) - (gnus-remove-from-range - (cdr (assoc mark backend-marks)) range)) + (range-remove (cdr (assoc mark backend-marks)) range)) ((eq what 'set) range)) backend-marks))))) diff --git a/lisp/gnus/nnimap.el b/lisp/gnus/nnimap.el index cff628061e9..afd5418912f 100644 --- a/lisp/gnus/nnimap.el +++ b/lisp/gnus/nnimap.el @@ -1660,13 +1660,13 @@ If LIMIT, first try to limit the search to the N last articles." (cdr (assoc '%Seen flags)) (cdr (assoc '%Deleted flags)))) (cdr (assoc '%Flagged flags))))) - (read (gnus-range-difference + (read (range-difference (cons start-article high) unread))) (when (> start-article 1) (setq read (gnus-range-nconcat (if (> start-article 1) - (gnus-sorted-range-intersection + (range-intersection (cons 1 (1- start-article)) (gnus-info-read info)) (gnus-info-read info)) @@ -1691,7 +1691,7 @@ If LIMIT, first try to limit the search to the N last articles." (pop old-marks) (when (and old-marks (> start-article 1)) - (setq old-marks (gnus-range-difference + (setq old-marks (range-difference old-marks (cons start-article high))) (setq new-marks (gnus-range-nconcat old-marks new-marks))) @@ -1702,15 +1702,15 @@ If LIMIT, first try to limit the search to the N last articles." (active (gnus-active group)) (unexists (if completep - (gnus-range-difference + (range-difference active (gnus-compress-sequence existing)) - (gnus-add-to-range + (range-add-list (cdr old-unexists) - (gnus-list-range-difference + (range-list-difference existing (gnus-active group)))))) (when (> (car active) 1) - (setq unexists (gnus-range-add + (setq unexists (range-concat (cons 1 (1- (car active))) unexists))) (if old-unexists @@ -1733,10 +1733,9 @@ If LIMIT, first try to limit the search to the N last articles." (defun nnimap-update-qresync-info (info existing vanished flags) ;; Add all the vanished articles to the list of read articles. (setf (gnus-info-read info) - (gnus-add-to-range - (gnus-add-to-range - (gnus-range-add (gnus-info-read info) - vanished) + (range-add-list + (range-add-list + (range-concat (gnus-info-read info) vanished) (cdr (assq '%Flagged flags))) (cdr (assq '%Seen flags)))) (let ((marks (gnus-info-marks info))) @@ -1750,9 +1749,9 @@ If LIMIT, first try to limit the search to the N last articles." (setq marks (delq ticks marks)) (pop ticks) ;; Add the new marks we got. - (setq ticks (gnus-add-to-range ticks new-marks)) + (setq ticks (range-add-list ticks new-marks)) ;; Remove the marks from messages that don't have them. - (setq ticks (gnus-remove-from-range + (setq ticks (range-remove ticks (gnus-compress-sequence (gnus-sorted-complement existing new-marks)))) @@ -1762,7 +1761,7 @@ If LIMIT, first try to limit the search to the N last articles." ;; Add vanished to the list of unexisting articles. (when vanished (let* ((old-unexists (assq 'unexist marks)) - (unexists (gnus-range-add (cdr old-unexists) vanished))) + (unexists (range-concat (cdr old-unexists) vanished))) (if old-unexists (setcdr old-unexists unexists) (push (cons 'unexist unexists) marks))) @@ -2242,7 +2241,7 @@ Return the server's response to the SELECT or EXAMINE command." (while (re-search-forward "^\\([0-9]+\\) OK\\b" nil t) (setq sequence (string-to-number (match-string 1))) (when (setq range (cadr (assq sequence sequences))) - (push (gnus-uncompress-range range) copied))) + (push (range-uncompress range) copied))) (gnus-compress-sequence (sort (apply #'nconc copied) #'<)))) (defun nnimap-new-articles (flags) diff --git a/lisp/gnus/nnmaildir.el b/lisp/gnus/nnmaildir.el index 690761a2d6c..30f473b1291 100644 --- a/lisp/gnus/nnmaildir.el +++ b/lisp/gnus/nnmaildir.el @@ -1006,10 +1006,10 @@ This variable is set by `nnmaildir-request-article'.") existing (nnmaildir--grp-nlist group) existing (mapcar #'car existing) existing (nreverse existing) - existing (gnus-compress-sequence existing 'always-list) + existing (range-compress-list existing) missing (list (cons 1 (nnmaildir--group-maxnum nnmaildir--cur-server group))) - missing (gnus-range-difference missing existing) + missing (range-difference missing existing) dir (nnmaildir--srv-dir nnmaildir--cur-server) dir (nnmaildir--srvgrp-dir dir gname) dir (nnmaildir--nndir dir) @@ -1076,10 +1076,10 @@ This variable is set by `nnmaildir-request-article'.") (let ((article (nnmaildir--flist-art flist prefix))) (when article (push (nnmaildir--art-num article) article-list)))))) - (setq ranges (gnus-add-to-range ranges (sort article-list #'<))))) + (setq ranges (range-add-list ranges (sort article-list #'<))))) (if (eq mark 'read) (setq read ranges) (if ranges (setq marks (cons (cons mark ranges) marks))))) - (setf (gnus-info-read info) (gnus-range-add read missing)) + (setf (gnus-info-read info) (range-concat read missing)) (gnus-info-set-marks info marks 'extend) (setf (nnmaildir--grp-mmth group) new-mmth) info))) @@ -1548,11 +1548,11 @@ This variable is set by `nnmaildir-request-article'.") (unless group (setf (nnmaildir--srv-error nnmaildir--cur-server) (if gname (concat "No such group: " gname) "No current group")) - (throw 'return (gnus-uncompress-range ranges))) + (throw 'return (range-uncompress ranges))) (setq gname (nnmaildir--grp-name group) pgname (nnmaildir--pgname nnmaildir--cur-server gname)) (if (nnmaildir--param pgname 'read-only) - (throw 'return (gnus-uncompress-range ranges))) + (throw 'return (range-uncompress ranges))) (setq time (nnmaildir--param pgname 'expire-age)) (unless time (setq time (or (and nnmail-expiry-wait-function @@ -1564,7 +1564,7 @@ This variable is set by `nnmaildir-request-article'.") (setq time (round (* time 86400)))))) (when no-force (unless (integerp time) ;; handle 'never - (throw 'return (gnus-uncompress-range ranges))) + (throw 'return (range-uncompress ranges))) (setq boundary (time-since time))) (setq dir (nnmaildir--srv-dir nnmaildir--cur-server) dir (nnmaildir--srvgrp-dir dir gname) @@ -1686,7 +1686,7 @@ This variable is set by `nnmaildir-request-article'.") (setf (nnmaildir--srv-error nnmaildir--cur-server) (concat "No such group: " gname)) (dolist (action actions) - (setq ranges (gnus-range-add ranges (car action)))) + (setq ranges (range-concat ranges (car action)))) (throw 'return ranges)) (setq nlist (nnmaildir--grp-nlist group) marksdir (nnmaildir--srv-dir nnmaildir--cur-server) diff --git a/lisp/gnus/nnmairix.el b/lisp/gnus/nnmairix.el index 8ca1cf0fe8b..4e8e329f983 100644 --- a/lisp/gnus/nnmairix.el +++ b/lisp/gnus/nnmairix.el @@ -597,7 +597,7 @@ Other back ends might or might not work.") (dolist (cur actions) (let ((type (nth 1 cur)) (cmdmarks (nth 2 cur)) - (range (gnus-uncompress-range (nth 0 cur))) + (range (range-uncompress (nth 0 cur))) mid ogroup temp) ;; number method (when (and corr (not (zerop (cadr corr)))) diff --git a/lisp/gnus/nnmbox.el b/lisp/gnus/nnmbox.el index 5a350aac746..96ecc34e156 100644 --- a/lisp/gnus/nnmbox.el +++ b/lisp/gnus/nnmbox.el @@ -529,7 +529,7 @@ ;; add article to index, either by building complete list ;; in reverse order, or as a list of ranges. (if (not nnmbox-group-building-active-articles) - (setcdr entry (gnus-add-to-range (cdr entry) (list article))) + (setcdr entry (range-add-list (cdr entry) (list article))) (when (memq article (cdr entry)) (switch-to-buffer nnmbox-mbox-buffer) (error "Article %s:%d already exists!" group article)) @@ -548,10 +548,10 @@ nnmbox-group-active-articles) (car nnmbox-group-active-articles))))) ;; remove article from index - (setcdr entry (gnus-remove-from-range (cdr entry) (list article))))) + (setcdr entry (range-remove (cdr entry) (list article))))) (defun nnmbox-is-article-active-p (article) - (gnus-member-of-range + (range-member-p article (cdr (assoc nnmbox-current-group nnmbox-group-active-articles)))) diff --git a/lisp/gnus/nnml.el b/lisp/gnus/nnml.el index afdb0c780a5..7fe2b516cce 100644 --- a/lisp/gnus/nnml.el +++ b/lisp/gnus/nnml.el @@ -1078,21 +1078,20 @@ Use the nov database for the current group if available." ;; #### doing anything on them. ;; 2 a/ read articles: (let ((read (gnus-info-read info))) - (setq read (gnus-remove-from-range read (list new-number))) - (when (gnus-member-of-range old-number read) - (setq read (gnus-remove-from-range read (list old-number))) - (setq read (gnus-add-to-range read (list new-number)))) + (setq read (range-remove read (list new-number))) + (when (range-member-p old-number read) + (setq read (range-remove read (list old-number))) + (setq read (range-add-list read (list new-number)))) (setf (gnus-info-read info) read)) ;; 2 b/ marked articles: (let ((oldmarks (gnus-info-marks info)) mark newmarks) (while (setq mark (pop oldmarks)) - (setcdr mark (gnus-remove-from-range (cdr mark) - (list new-number))) - (when (gnus-member-of-range old-number (cdr mark)) - (setcdr mark (gnus-remove-from-range (cdr mark) - (list old-number))) - (setcdr mark (gnus-add-to-range (cdr mark) + (setcdr mark (range-remove (cdr mark) (list new-number))) + (when (range-member-p old-number (cdr mark)) + (setcdr mark (range-remove (cdr mark) + (list old-number))) + (setcdr mark (range-add-list (cdr mark) (list new-number)))) (push mark newmarks)) (setf (gnus-info-marks info) newmarks)) diff --git a/lisp/gnus/nnselect.el b/lisp/gnus/nnselect.el index 9d744ea411e..205456a57df 100644 --- a/lisp/gnus/nnselect.el +++ b/lisp/gnus/nnselect.el @@ -207,7 +207,7 @@ as `(keyfunc member)' and the corresponding element is just (inline-quote (cond ((eq ,type 'range) - (nnselect-categorize (gnus-uncompress-range ,articles) + (nnselect-categorize (range-uncompress ,articles) #'nnselect-article-group #'nnselect-article-number)) ((eq ,type 'tuple) (nnselect-categorize ,articles @@ -542,10 +542,10 @@ If this variable is nil, or if the provided function returns nil, (group-info (gnus-get-info artgroup)) (marks (gnus-info-marks group-info)) (unread (gnus-uncompress-sequence - (gnus-range-difference (gnus-active artgroup) - (gnus-info-read group-info))))) + (range-difference (gnus-active artgroup) + (gnus-info-read group-info))))) (setf (gnus-info-read info) - (gnus-add-to-range + (range-add-list (gnus-info-read info) (delq nil (mapcar (lambda (art) @@ -567,7 +567,7 @@ If this variable is nil, or if the provided function returns nil, artids)) (t (setq mark-list - (gnus-uncompress-range mark-list)) + (range-uncompress mark-list)) (mapcar (lambda (id) (when (memq (cdr id) mark-list) @@ -866,16 +866,16 @@ article came from is also searched." (when (and (gnus-check-backend-function 'request-set-mark artgroup) (not (gnus-article-unpropagatable-p type))) - (let* ((old (gnus-list-range-intersection + (let* ((old (range-list-intersection artlist (alist-get type (gnus-info-marks group-info)))) - (del (gnus-remove-from-range (copy-tree old) list)) - (add (gnus-remove-from-range (copy-tree list) old))) + (del (range-remove (copy-tree old) list)) + (add (range-remove (copy-tree list) old))) (when add (push (list add 'add (list type)) delta-marks)) (when del ;; Don't delete marks from outside the active range. ;; This shouldn't happen, but is a sanity check. - (setq del (gnus-sorted-range-intersection + (setq del (range-intersection (gnus-active artgroup) del)) (push (list del 'del (list type)) delta-marks)))) @@ -910,18 +910,18 @@ article came from is also searched." (< (car elt1) (car elt2)))))) (t (setq list - (gnus-compress-sequence + (range-compress-list (gnus-sorted-union (gnus-sorted-difference (gnus-uncompress-sequence (alist-get type (gnus-info-marks group-info))) artlist) - (sort list #'<)) t))) + (sort list #'<))))) ;; When exiting the group, everything that's previously been ;; unseen is now seen. (when (eq type 'seen) - (setq list (gnus-range-add + (setq list (range-concat list (cdr (assoc artgroup select-unseen)))))) (when (or list (eq type 'unexist)) @@ -944,9 +944,9 @@ article came from is also searched." ;; update read and unread (gnus-update-read-articles artgroup - (gnus-uncompress-range - (gnus-add-to-range - (gnus-remove-from-range + (range-uncompress + (range-add-list + (range-remove old-unread (cdr (assoc artgroup select-reads))) (sort (cdr (assoc artgroup select-unreads)) #'<)))) diff --git a/lisp/gnus/nnvirtual.el b/lisp/gnus/nnvirtual.el index 7478a2dd0af..cc87a707ce6 100644 --- a/lisp/gnus/nnvirtual.el +++ b/lisp/gnus/nnvirtual.el @@ -365,7 +365,7 @@ It is computed from the marks of individual component groups.") (lambda (article) (nnvirtual-reverse-map-article group article)) - (gnus-uncompress-range + (range-uncompress (gnus-group-expire-articles-1 group)))))) (sort (delq nil unexpired) #'<))) diff --git a/test/lisp/emacs-lisp/range-tests.el b/test/lisp/emacs-lisp/range-tests.el new file mode 100644 index 00000000000..d3abbf9da31 --- /dev/null +++ b/test/lisp/emacs-lisp/range-tests.el @@ -0,0 +1,65 @@ +;;; range-tests.el --- Tests for range.el -*- lexical-binding: t; -*- + +;; Copyright (C) 2021 Free Software Foundation, Inc. + +;; This file is part of GNU Emacs. + +;; GNU Emacs 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. + +;; GNU Emacs 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 GNU Emacs. If not, see . + +;;; Commentary: + +;; + +;;; Code: + +(require 'range) +(require 'ert) +(require 'ert-x) + +(ert-deftest ranges () + (should (equal (range-compress-list '(2 3 4 5 9 11 12 13)) + '((2 . 5) 9 (11 . 13)))) + (should (equal (range-uncompress '((2 . 5) 9 (11 . 13))) + '(2 3 4 5 9 11 12 13))) + (should (equal (range-normalize '(1 . 2)) + '((1 . 2)))) + (should (equal (range-difference '((1 . 10)) + '((2 . 7))) + '(1 (8 . 10)))) + (should (equal (range-intersection '((2 . 5) 9 (11 . 13)) + '((5 . 12))) + '(5 9 (11 . 12)))) + (should (equal (range-add-list '((2 . 5) 9 (11 . 13)) + '(10 11 12 15 16 17)) + '((2 . 5) (9 . 10) (11 . 13) (15 . 17)))) + (should (equal (range-remove (copy-tree '((2 . 5) 9 (11 . 13))) + '((5 . 9))) + '((2 . 4) (11 . 13)))) + (should (range-member-p 9 '((2 . 5) 9 (11 . 13)))) + (should (range-member-p 12 '((2 . 5) 9 (11 . 13)))) + (should (equal (range-list-intersection + '(4 5 6 7 8 9) + '((2 . 5) 9 (11 . 13))) + '(4 5 9))) + (should (equal (range-list-difference + '(4 5 6 7 8 9) + '((2 . 5) 9 (11 . 13))) + '(6 7 8))) + (should (equal (range-length '((2 . 5) 9 (11 . 13))) + 8)) + (should (equal (range-concat '((2 . 5) 9 (11 . 13)) + '(6 (12 . 15))) + '((2 . 6) 9 (11 . 15))))) + +;;; range-tests.el ends here -- cgit v1.2.1 From e2c8091113404971de75a893fb30cac591a82694 Mon Sep 17 00:00:00 2001 From: Lars Ingebrigtsen Date: Mon, 17 Jan 2022 15:47:37 +0100 Subject: Add support for functions that deal with Unicode scripts * admin/unidata/Makefile.in (${unidir}/uni-scripts.el): Build uni-scripts.el. * admin/unidata/Scripts.txt: * admin/unidata/ScriptExtensions.txt: * admin/unidata/PropertyValueAliases.txt: New files from Unicode. * admin/unidata/README: Update. * admin/unidata/unidata-gen.el (unidata-gen-charprop): Allow writing other data, too. (unidata-gen-scripts, unidata-gen--read-script-aliases) (unidata-gen--insert-file): New functions to parse the Script* files. * lisp/international/textsec.el: Implement some functions that work on scripts. --- admin/unidata/Makefile.in | 10 +- admin/unidata/PropertyValueAliases.txt | 1615 ++++++++++++++++ admin/unidata/README | 12 + admin/unidata/ScriptExtensions.txt | 628 +++++++ admin/unidata/Scripts.txt | 2991 ++++++++++++++++++++++++++++++ admin/unidata/unidata-gen.el | 117 +- etc/NEWS | 4 + lisp/international/textsec.el | 95 + test/lisp/international/textsec-tests.el | 72 + 9 files changed, 5536 insertions(+), 8 deletions(-) create mode 100644 admin/unidata/PropertyValueAliases.txt create mode 100644 admin/unidata/ScriptExtensions.txt create mode 100644 admin/unidata/Scripts.txt create mode 100644 lisp/international/textsec.el create mode 100644 test/lisp/international/textsec-tests.el diff --git a/admin/unidata/Makefile.in b/admin/unidata/Makefile.in index e75010dc2b8..07b0702fd08 100644 --- a/admin/unidata/Makefile.in +++ b/admin/unidata/Makefile.in @@ -44,7 +44,8 @@ unifiles = $(addprefix ${unidir}/,$(sort $(shell sed -n 's/^[ \t][ \t]*${lparen} .PHONY: all all: ${top_srcdir}/src/macuvs.h ${unifiles} ${unidir}/charscript.el \ - ${unidir}/charprop.el ${unidir}/emoji-zwj.el ${unidir}/emoji-labels.el + ${unidir}/charprop.el ${unidir}/emoji-zwj.el ${unidir}/emoji-labels.el \ + ${unidir}/uni-scripts.el ## Specify .elc as an order-only prereq so as to not needlessly rebuild ## target just because the .elc is missing. @@ -82,6 +83,13 @@ ${unidir}/emoji-labels.el: ${unidir}/../international/emoji.el \ ${srcdir}/emoji-test.txt $(AM_V_GEN)${emacs} -l emoji.el -f emoji--generate-file $@ +${unidir}/uni-scripts.el: ${srcdir}/unidata-gen.el \ + ${srcdir}/Scripts.txt \ + ${srcdir}/ScriptExtensions.txt \ + ${srcdir}/PropertyValueAliases.txt + $(AM_V_GEN)${emacs} -L ${srcdir} \ + -l unidata-gen -f unidata-gen-scripts $@ + .PHONY: charscript.el charscript.el: ${unidir}/charscript.el diff --git a/admin/unidata/PropertyValueAliases.txt b/admin/unidata/PropertyValueAliases.txt new file mode 100644 index 00000000000..bdc13857dcb --- /dev/null +++ b/admin/unidata/PropertyValueAliases.txt @@ -0,0 +1,1615 @@ +# PropertyValueAliases-14.0.0.txt +# Date: 2021-05-10, 21:08:53 GMT +# © 2021 Unicode®, Inc. +# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries. +# For terms of use, see http://www.unicode.org/terms_of_use.html +# +# Unicode Character Database +# For documentation, see http://www.unicode.org/reports/tr44/ +# +# This file contains aliases for property values used in the UCD. +# These names can be used for XML formats of UCD data, for regular-expression +# property tests, and other programmatic textual descriptions of Unicode data. +# +# The names may be translated in appropriate environments, and additional +# aliases may be useful. +# +# FORMAT +# +# Each line describes a property value name. +# This consists of three or more fields, separated by semicolons. +# +# First Field: The first field describes the property for which that +# property value name is used. +# +# Second Field: The second field is the short name for the property value. +# It is typically an abbreviation, but in a number of cases it is simply +# a duplicate of the "long name" in the third field. +# +# Third Field: The third field is the long name for the property value, +# typically the formal name used in documentation about the property value. +# +# In the case of Canonical_Combining_Class (ccc), there are 4 fields: +# The second field is numeric, the third is the short name, and the fourth is the long name. +# +# The above are the preferred aliases. Other aliases may be listed in additional fields. +# +# Loose matching should be applied to all property names and property values, with +# the exception of String Property values. With loose matching of property names and +# values, the case distinctions, whitespace, hyphens, and '_' are ignored. +# For Numeric Property values, numeric equivalence is applied: thus "01.00" +# is equivalent to "1". +# +# NOTE: Property value names are NOT unique across properties. For example: +# +# AL means Arabic Letter for the Bidi_Class property, and +# AL means Above_Left for the Canonical_Combining_Class property, and +# AL means Alphabetic for the Line_Break property. +# +# In addition, some property names may be the same as some property value names. +# For example: +# +# sc means the Script property, and +# Sc means the General_Category property value Currency_Symbol (Sc) +# +# The combination of property value and property name is, however, unique. +# +# For more information, see UAX #44, Unicode Character Database, and +# UTS #18, Unicode Regular Expressions. +# ================================================ + + +# ASCII_Hex_Digit (AHex) + +AHex; N ; No ; F ; False +AHex; Y ; Yes ; T ; True + +# Age (age) + +age; 1.1 ; V1_1 +age; 2.0 ; V2_0 +age; 2.1 ; V2_1 +age; 3.0 ; V3_0 +age; 3.1 ; V3_1 +age; 3.2 ; V3_2 +age; 4.0 ; V4_0 +age; 4.1 ; V4_1 +age; 5.0 ; V5_0 +age; 5.1 ; V5_1 +age; 5.2 ; V5_2 +age; 6.0 ; V6_0 +age; 6.1 ; V6_1 +age; 6.2 ; V6_2 +age; 6.3 ; V6_3 +age; 7.0 ; V7_0 +age; 8.0 ; V8_0 +age; 9.0 ; V9_0 +age; 10.0 ; V10_0 +age; 11.0 ; V11_0 +age; 12.0 ; V12_0 +age; 12.1 ; V12_1 +age; 13.0 ; V13_0 +age; 14.0 ; V14_0 +age; NA ; Unassigned + +# Alphabetic (Alpha) + +Alpha; N ; No ; F ; False +Alpha; Y ; Yes ; T ; True + +# Bidi_Class (bc) + +bc ; AL ; Arabic_Letter +bc ; AN ; Arabic_Number +bc ; B ; Paragraph_Separator +bc ; BN ; Boundary_Neutral +bc ; CS ; Common_Separator +bc ; EN ; European_Number +bc ; ES ; European_Separator +bc ; ET ; European_Terminator +bc ; FSI ; First_Strong_Isolate +bc ; L ; Left_To_Right +bc ; LRE ; Left_To_Right_Embedding +bc ; LRI ; Left_To_Right_Isolate +bc ; LRO ; Left_To_Right_Override +bc ; NSM ; Nonspacing_Mark +bc ; ON ; Other_Neutral +bc ; PDF ; Pop_Directional_Format +bc ; PDI ; Pop_Directional_Isolate +bc ; R ; Right_To_Left +bc ; RLE ; Right_To_Left_Embedding +bc ; RLI ; Right_To_Left_Isolate +bc ; RLO ; Right_To_Left_Override +bc ; S ; Segment_Separator +bc ; WS ; White_Space + +# Bidi_Control (Bidi_C) + +Bidi_C; N ; No ; F ; False +Bidi_C; Y ; Yes ; T ; True + +# Bidi_Mirrored (Bidi_M) + +Bidi_M; N ; No ; F ; False +Bidi_M; Y ; Yes ; T ; True + +# Bidi_Mirroring_Glyph (bmg) + +# @missing: 0000..10FFFF; Bidi_Mirroring_Glyph; + +# Bidi_Paired_Bracket (bpb) + +# @missing: 0000..10FFFF; Bidi_Paired_Bracket; + +# Bidi_Paired_Bracket_Type (bpt) + +bpt; c ; Close +bpt; n ; None +bpt; o ; Open +# @missing: 0000..10FFFF; Bidi_Paired_Bracket_Type; n + +# Block (blk) + +blk; Adlam ; Adlam +blk; Aegean_Numbers ; Aegean_Numbers +blk; Ahom ; Ahom +blk; Alchemical ; Alchemical_Symbols +blk; Alphabetic_PF ; Alphabetic_Presentation_Forms +blk; Anatolian_Hieroglyphs ; Anatolian_Hieroglyphs +blk; Ancient_Greek_Music ; Ancient_Greek_Musical_Notation +blk; Ancient_Greek_Numbers ; Ancient_Greek_Numbers +blk; Ancient_Symbols ; Ancient_Symbols +blk; Arabic ; Arabic +blk; Arabic_Ext_A ; Arabic_Extended_A +blk; Arabic_Ext_B ; Arabic_Extended_B +blk; Arabic_Math ; Arabic_Mathematical_Alphabetic_Symbols +blk; Arabic_PF_A ; Arabic_Presentation_Forms_A ; Arabic_Presentation_Forms-A +blk; Arabic_PF_B ; Arabic_Presentation_Forms_B +blk; Arabic_Sup ; Arabic_Supplement +blk; Armenian ; Armenian +blk; Arrows ; Arrows +blk; ASCII ; Basic_Latin +blk; Avestan ; Avestan +blk; Balinese ; Balinese +blk; Bamum ; Bamum +blk; Bamum_Sup ; Bamum_Supplement +blk; Bassa_Vah ; Bassa_Vah +blk; Batak ; Batak +blk; Bengali ; Bengali +blk; Bhaiksuki ; Bhaiksuki +blk; Block_Elements ; Block_Elements +blk; Bopomofo ; Bopomofo +blk; Bopomofo_Ext ; Bopomofo_Extended +blk; Box_Drawing ; Box_Drawing +blk; Brahmi ; Brahmi +blk; Braille ; Braille_Patterns +blk; Buginese ; Buginese +blk; Buhid ; Buhid +blk; Byzantine_Music ; Byzantine_Musical_Symbols +blk; Carian ; Carian +blk; Caucasian_Albanian ; Caucasian_Albanian +blk; Chakma ; Chakma +blk; Cham ; Cham +blk; Cherokee ; Cherokee +blk; Cherokee_Sup ; Cherokee_Supplement +blk; Chess_Symbols ; Chess_Symbols +blk; Chorasmian ; Chorasmian +blk; CJK ; CJK_Unified_Ideographs +blk; CJK_Compat ; CJK_Compatibility +blk; CJK_Compat_Forms ; CJK_Compatibility_Forms +blk; CJK_Compat_Ideographs ; CJK_Compatibility_Ideographs +blk; CJK_Compat_Ideographs_Sup ; CJK_Compatibility_Ideographs_Supplement +blk; CJK_Ext_A ; CJK_Unified_Ideographs_Extension_A +blk; CJK_Ext_B ; CJK_Unified_Ideographs_Extension_B +blk; CJK_Ext_C ; CJK_Unified_Ideographs_Extension_C +blk; CJK_Ext_D ; CJK_Unified_Ideographs_Extension_D +blk; CJK_Ext_E ; CJK_Unified_Ideographs_Extension_E +blk; CJK_Ext_F ; CJK_Unified_Ideographs_Extension_F +blk; CJK_Ext_G ; CJK_Unified_Ideographs_Extension_G +blk; CJK_Radicals_Sup ; CJK_Radicals_Supplement +blk; CJK_Strokes ; CJK_Strokes +blk; CJK_Symbols ; CJK_Symbols_And_Punctuation +blk; Compat_Jamo ; Hangul_Compatibility_Jamo +blk; Control_Pictures ; Control_Pictures +blk; Coptic ; Coptic +blk; Coptic_Epact_Numbers ; Coptic_Epact_Numbers +blk; Counting_Rod ; Counting_Rod_Numerals +blk; Cuneiform ; Cuneiform +blk; Cuneiform_Numbers ; Cuneiform_Numbers_And_Punctuation +blk; Currency_Symbols ; Currency_Symbols +blk; Cypriot_Syllabary ; Cypriot_Syllabary +blk; Cypro_Minoan ; Cypro_Minoan +blk; Cyrillic ; Cyrillic +blk; Cyrillic_Ext_A ; Cyrillic_Extended_A +blk; Cyrillic_Ext_B ; Cyrillic_Extended_B +blk; Cyrillic_Ext_C ; Cyrillic_Extended_C +blk; Cyrillic_Sup ; Cyrillic_Supplement ; Cyrillic_Supplementary +blk; Deseret ; Deseret +blk; Devanagari ; Devanagari +blk; Devanagari_Ext ; Devanagari_Extended +blk; Diacriticals ; Combining_Diacritical_Marks +blk; Diacriticals_Ext ; Combining_Diacritical_Marks_Extended +blk; Diacriticals_For_Symbols ; Combining_Diacritical_Marks_For_Symbols; Combining_Marks_For_Symbols +blk; Diacriticals_Sup ; Combining_Diacritical_Marks_Supplement +blk; Dingbats ; Dingbats +blk; Dives_Akuru ; Dives_Akuru +blk; Dogra ; Dogra +blk; Domino ; Domino_Tiles +blk; Duployan ; Duployan +blk; Early_Dynastic_Cuneiform ; Early_Dynastic_Cuneiform +blk; Egyptian_Hieroglyph_Format_Controls; Egyptian_Hieroglyph_Format_Controls +blk; Egyptian_Hieroglyphs ; Egyptian_Hieroglyphs +blk; Elbasan ; Elbasan +blk; Elymaic ; Elymaic +blk; Emoticons ; Emoticons +blk; Enclosed_Alphanum ; Enclosed_Alphanumerics +blk; Enclosed_Alphanum_Sup ; Enclosed_Alphanumeric_Supplement +blk; Enclosed_CJK ; Enclosed_CJK_Letters_And_Months +blk; Enclosed_Ideographic_Sup ; Enclosed_Ideographic_Supplement +blk; Ethiopic ; Ethiopic +blk; Ethiopic_Ext ; Ethiopic_Extended +blk; Ethiopic_Ext_A ; Ethiopic_Extended_A +blk; Ethiopic_Ext_B ; Ethiopic_Extended_B +blk; Ethiopic_Sup ; Ethiopic_Supplement +blk; Geometric_Shapes ; Geometric_Shapes +blk; Geometric_Shapes_Ext ; Geometric_Shapes_Extended +blk; Georgian ; Georgian +blk; Georgian_Ext ; Georgian_Extended +blk; Georgian_Sup ; Georgian_Supplement +blk; Glagolitic ; Glagolitic +blk; Glagolitic_Sup ; Glagolitic_Supplement +blk; Gothic ; Gothic +blk; Grantha ; Grantha +blk; Greek ; Greek_And_Coptic +blk; Greek_Ext ; Greek_Extended +blk; Gujarati ; Gujarati +blk; Gunjala_Gondi ; Gunjala_Gondi +blk; Gurmukhi ; Gurmukhi +blk; Half_And_Full_Forms ; Halfwidth_And_Fullwidth_Forms +blk; Half_Marks ; Combining_Half_Marks +blk; Hangul ; Hangul_Syllables +blk; Hanifi_Rohingya ; Hanifi_Rohingya +blk; Hanunoo ; Hanunoo +blk; Hatran ; Hatran +blk; Hebrew ; Hebrew +blk; High_PU_Surrogates ; High_Private_Use_Surrogates +blk; High_Surrogates ; High_Surrogates +blk; Hiragana ; Hiragana +blk; IDC ; Ideographic_Description_Characters +blk; Ideographic_Symbols ; Ideographic_Symbols_And_Punctuation +blk; Imperial_Aramaic ; Imperial_Aramaic +blk; Indic_Number_Forms ; Common_Indic_Number_Forms +blk; Indic_Siyaq_Numbers ; Indic_Siyaq_Numbers +blk; Inscriptional_Pahlavi ; Inscriptional_Pahlavi +blk; Inscriptional_Parthian ; Inscriptional_Parthian +blk; IPA_Ext ; IPA_Extensions +blk; Jamo ; Hangul_Jamo +blk; Jamo_Ext_A ; Hangul_Jamo_Extended_A +blk; Jamo_Ext_B ; Hangul_Jamo_Extended_B +blk; Javanese ; Javanese +blk; Kaithi ; Kaithi +blk; Kana_Ext_A ; Kana_Extended_A +blk; Kana_Ext_B ; Kana_Extended_B +blk; Kana_Sup ; Kana_Supplement +blk; Kanbun ; Kanbun +blk; Kangxi ; Kangxi_Radicals +blk; Kannada ; Kannada +blk; Katakana ; Katakana +blk; Katakana_Ext ; Katakana_Phonetic_Extensions +blk; Kayah_Li ; Kayah_Li +blk; Kharoshthi ; Kharoshthi +blk; Khitan_Small_Script ; Khitan_Small_Script +blk; Khmer ; Khmer +blk; Khmer_Symbols ; Khmer_Symbols +blk; Khojki ; Khojki +blk; Khudawadi ; Khudawadi +blk; Lao ; Lao +blk; Latin_1_Sup ; Latin_1_Supplement ; Latin_1 +blk; Latin_Ext_A ; Latin_Extended_A +blk; Latin_Ext_Additional ; Latin_Extended_Additional +blk; Latin_Ext_B ; Latin_Extended_B +blk; Latin_Ext_C ; Latin_Extended_C +blk; Latin_Ext_D ; Latin_Extended_D +blk; Latin_Ext_E ; Latin_Extended_E +blk; Latin_Ext_F ; Latin_Extended_F +blk; Latin_Ext_G ; Latin_Extended_G +blk; Lepcha ; Lepcha +blk; Letterlike_Symbols ; Letterlike_Symbols +blk; Limbu ; Limbu +blk; Linear_A ; Linear_A +blk; Linear_B_Ideograms ; Linear_B_Ideograms +blk; Linear_B_Syllabary ; Linear_B_Syllabary +blk; Lisu ; Lisu +blk; Lisu_Sup ; Lisu_Supplement +blk; Low_Surrogates ; Low_Surrogates +blk; Lycian ; Lycian +blk; Lydian ; Lydian +blk; Mahajani ; Mahajani +blk; Mahjong ; Mahjong_Tiles +blk; Makasar ; Makasar +blk; Malayalam ; Malayalam +blk; Mandaic ; Mandaic +blk; Manichaean ; Manichaean +blk; Marchen ; Marchen +blk; Masaram_Gondi ; Masaram_Gondi +blk; Math_Alphanum ; Mathematical_Alphanumeric_Symbols +blk; Math_Operators ; Mathematical_Operators +blk; Mayan_Numerals ; Mayan_Numerals +blk; Medefaidrin ; Medefaidrin +blk; Meetei_Mayek ; Meetei_Mayek +blk; Meetei_Mayek_Ext ; Meetei_Mayek_Extensions +blk; Mende_Kikakui ; Mende_Kikakui +blk; Meroitic_Cursive ; Meroitic_Cursive +blk; Meroitic_Hieroglyphs ; Meroitic_Hieroglyphs +blk; Miao ; Miao +blk; Misc_Arrows ; Miscellaneous_Symbols_And_Arrows +blk; Misc_Math_Symbols_A ; Miscellaneous_Mathematical_Symbols_A +blk; Misc_Math_Symbols_B ; Miscellaneous_Mathematical_Symbols_B +blk; Misc_Pictographs ; Miscellaneous_Symbols_And_Pictographs +blk; Misc_Symbols ; Miscellaneous_Symbols +blk; Misc_Technical ; Miscellaneous_Technical +blk; Modi ; Modi +blk; Modifier_Letters ; Spacing_Modifier_Letters +blk; Modifier_Tone_Letters ; Modifier_Tone_Letters +blk; Mongolian ; Mongolian +blk; Mongolian_Sup ; Mongolian_Supplement +blk; Mro ; Mro +blk; Multani ; Multani +blk; Music ; Musical_Symbols +blk; Myanmar ; Myanmar +blk; Myanmar_Ext_A ; Myanmar_Extended_A +blk; Myanmar_Ext_B ; Myanmar_Extended_B +blk; Nabataean ; Nabataean +blk; Nandinagari ; Nandinagari +blk; NB ; No_Block +blk; New_Tai_Lue ; New_Tai_Lue +blk; Newa ; Newa +blk; NKo ; NKo +blk; Number_Forms ; Number_Forms +blk; Nushu ; Nushu +blk; Nyiakeng_Puachue_Hmong ; Nyiakeng_Puachue_Hmong +blk; OCR ; Optical_Character_Recognition +blk; Ogham ; Ogham +blk; Ol_Chiki ; Ol_Chiki +blk; Old_Hungarian ; Old_Hungarian +blk; Old_Italic ; Old_Italic +blk; Old_North_Arabian ; Old_North_Arabian +blk; Old_Permic ; Old_Permic +blk; Old_Persian ; Old_Persian +blk; Old_Sogdian ; Old_Sogdian +blk; Old_South_Arabian ; Old_South_Arabian +blk; Old_Turkic ; Old_Turkic +blk; Old_Uyghur ; Old_Uyghur +blk; Oriya ; Oriya +blk; Ornamental_Dingbats ; Ornamental_Dingbats +blk; Osage ; Osage +blk; Osmanya ; Osmanya +blk; Ottoman_Siyaq_Numbers ; Ottoman_Siyaq_Numbers +blk; Pahawh_Hmong ; Pahawh_Hmong +blk; Palmyrene ; Palmyrene +blk; Pau_Cin_Hau ; Pau_Cin_Hau +blk; Phags_Pa ; Phags_Pa +blk; Phaistos ; Phaistos_Disc +blk; Phoenician ; Phoenician +blk; Phonetic_Ext ; Phonetic_Extensions +blk; Phonetic_Ext_Sup ; Phonetic_Extensions_Supplement +blk; Playing_Cards ; Playing_Cards +blk; Psalter_Pahlavi ; Psalter_Pahlavi +blk; PUA ; Private_Use_Area ; Private_Use +blk; Punctuation ; General_Punctuation +blk; Rejang ; Rejang +blk; Rumi ; Rumi_Numeral_Symbols +blk; Runic ; Runic +blk; Samaritan ; Samaritan +blk; Saurashtra ; Saurashtra +blk; Sharada ; Sharada +blk; Shavian ; Shavian +blk; Shorthand_Format_Controls ; Shorthand_Format_Controls +blk; Siddham ; Siddham +blk; Sinhala ; Sinhala +blk; Sinhala_Archaic_Numbers ; Sinhala_Archaic_Numbers +blk; Small_Forms ; Small_Form_Variants +blk; Small_Kana_Ext ; Small_Kana_Extension +blk; Sogdian ; Sogdian +blk; Sora_Sompeng ; Sora_Sompeng +blk; Soyombo ; Soyombo +blk; Specials ; Specials +blk; Sundanese ; Sundanese +blk; Sundanese_Sup ; Sundanese_Supplement +blk; Sup_Arrows_A ; Supplemental_Arrows_A +blk; Sup_Arrows_B ; Supplemental_Arrows_B +blk; Sup_Arrows_C ; Supplemental_Arrows_C +blk; Sup_Math_Operators ; Supplemental_Mathematical_Operators +blk; Sup_PUA_A ; Supplementary_Private_Use_Area_A +blk; Sup_PUA_B ; Supplementary_Private_Use_Area_B +blk; Sup_Punctuation ; Supplemental_Punctuation +blk; Sup_Symbols_And_Pictographs ; Supplemental_Symbols_And_Pictographs +blk; Super_And_Sub ; Superscripts_And_Subscripts +blk; Sutton_SignWriting ; Sutton_SignWriting +blk; Syloti_Nagri ; Syloti_Nagri +blk; Symbols_And_Pictographs_Ext_A ; Symbols_And_Pictographs_Extended_A +blk; Symbols_For_Legacy_Computing ; Symbols_For_Legacy_Computing +blk; Syriac ; Syriac +blk; Syriac_Sup ; Syriac_Supplement +blk; Tagalog ; Tagalog +blk; Tagbanwa ; Tagbanwa +blk; Tags ; Tags +blk; Tai_Le ; Tai_Le +blk; Tai_Tham ; Tai_Tham +blk; Tai_Viet ; Tai_Viet +blk; Tai_Xuan_Jing ; Tai_Xuan_Jing_Symbols +blk; Takri ; Takri +blk; Tamil ; Tamil +blk; Tamil_Sup ; Tamil_Supplement +blk; Tangsa ; Tangsa +blk; Tangut ; Tangut +blk; Tangut_Components ; Tangut_Components +blk; Tangut_Sup ; Tangut_Supplement +blk; Telugu ; Telugu +blk; Thaana ; Thaana +blk; Thai ; Thai +blk; Tibetan ; Tibetan +blk; Tifinagh ; Tifinagh +blk; Tirhuta ; Tirhuta +blk; Toto ; Toto +blk; Transport_And_Map ; Transport_And_Map_Symbols +blk; UCAS ; Unified_Canadian_Aboriginal_Syllabics; Canadian_Syllabics +blk; UCAS_Ext ; Unified_Canadian_Aboriginal_Syllabics_Extended +blk; UCAS_Ext_A ; Unified_Canadian_Aboriginal_Syllabics_Extended_A +blk; Ugaritic ; Ugaritic +blk; Vai ; Vai +blk; Vedic_Ext ; Vedic_Extensions +blk; Vertical_Forms ; Vertical_Forms +blk; Vithkuqi ; Vithkuqi +blk; VS ; Variation_Selectors +blk; VS_Sup ; Variation_Selectors_Supplement +blk; Wancho ; Wancho +blk; Warang_Citi ; Warang_Citi +blk; Yezidi ; Yezidi +blk; Yi_Radicals ; Yi_Radicals +blk; Yi_Syllables ; Yi_Syllables +blk; Yijing ; Yijing_Hexagram_Symbols +blk; Zanabazar_Square ; Zanabazar_Square +blk; Znamenny_Music ; Znamenny_Musical_Notation + +# Canonical_Combining_Class (ccc) + +ccc; 0; NR ; Not_Reordered +ccc; 1; OV ; Overlay +ccc; 6; HANR ; Han_Reading +ccc; 7; NK ; Nukta +ccc; 8; KV ; Kana_Voicing +ccc; 9; VR ; Virama +ccc; 10; CCC10 ; CCC10 +ccc; 11; CCC11 ; CCC11 +ccc; 12; CCC12 ; CCC12 +ccc; 13; CCC13 ; CCC13 +ccc; 14; CCC14 ; CCC14 +ccc; 15; CCC15 ; CCC15 +ccc; 16; CCC16 ; CCC16 +ccc; 17; CCC17 ; CCC17 +ccc; 18; CCC18 ; CCC18 +ccc; 19; CCC19 ; CCC19 +ccc; 20; CCC20 ; CCC20 +ccc; 21; CCC21 ; CCC21 +ccc; 22; CCC22 ; CCC22 +ccc; 23; CCC23 ; CCC23 +ccc; 24; CCC24 ; CCC24 +ccc; 25; CCC25 ; CCC25 +ccc; 26; CCC26 ; CCC26 +ccc; 27; CCC27 ; CCC27 +ccc; 28; CCC28 ; CCC28 +ccc; 29; CCC29 ; CCC29 +ccc; 30; CCC30 ; CCC30 +ccc; 31; CCC31 ; CCC31 +ccc; 32; CCC32 ; CCC32 +ccc; 33; CCC33 ; CCC33 +ccc; 34; CCC34 ; CCC34 +ccc; 35; CCC35 ; CCC35 +ccc; 36; CCC36 ; CCC36 +ccc; 84; CCC84 ; CCC84 +ccc; 91; CCC91 ; CCC91 +ccc; 103; CCC103 ; CCC103 +ccc; 107; CCC107 ; CCC107 +ccc; 118; CCC118 ; CCC118 +ccc; 122; CCC122 ; CCC122 +ccc; 129; CCC129 ; CCC129 +ccc; 130; CCC130 ; CCC130 +ccc; 132; CCC132 ; CCC132 +ccc; 133; CCC133 ; CCC133 # RESERVED +ccc; 200; ATBL ; Attached_Below_Left +ccc; 202; ATB ; Attached_Below +ccc; 214; ATA ; Attached_Above +ccc; 216; ATAR ; Attached_Above_Right +ccc; 218; BL ; Below_Left +ccc; 220; B ; Below +ccc; 222; BR ; Below_Right +ccc; 224; L ; Left +ccc; 226; R ; Right +ccc; 228; AL ; Above_Left +ccc; 230; A ; Above +ccc; 232; AR ; Above_Right +ccc; 233; DB ; Double_Below +ccc; 234; DA ; Double_Above +ccc; 240; IS ; Iota_Subscript + +# Case_Folding (cf) + +# @missing: 0000..10FFFF; Case_Folding; + +# Case_Ignorable (CI) + +CI ; N ; No ; F ; False +CI ; Y ; Yes ; T ; True + +# Cased (Cased) + +Cased; N ; No ; F ; False +Cased; Y ; Yes ; T ; True + +# Changes_When_Casefolded (CWCF) + +CWCF; N ; No ; F ; False +CWCF; Y ; Yes ; T ; True + +# Changes_When_Casemapped (CWCM) + +CWCM; N ; No ; F ; False +CWCM; Y ; Yes ; T ; True + +# Changes_When_Lowercased (CWL) + +CWL; N ; No ; F ; False +CWL; Y ; Yes ; T ; True + +# Changes_When_NFKC_Casefolded (CWKCF) + +CWKCF; N ; No ; F ; False +CWKCF; Y ; Yes ; T ; True + +# Changes_When_Titlecased (CWT) + +CWT; N ; No ; F ; False +CWT; Y ; Yes ; T ; True + +# Changes_When_Uppercased (CWU) + +CWU; N ; No ; F ; False +CWU; Y ; Yes ; T ; True + +# Composition_Exclusion (CE) + +CE ; N ; No ; F ; False +CE ; Y ; Yes ; T ; True + +# Dash (Dash) + +Dash; N ; No ; F ; False +Dash; Y ; Yes ; T ; True + +# Decomposition_Mapping (dm) + +# @missing: 0000..10FFFF; Decomposition_Mapping; + +# Decomposition_Type (dt) + +dt ; Can ; Canonical ; can +dt ; Com ; Compat ; com +dt ; Enc ; Circle ; enc +dt ; Fin ; Final ; fin +dt ; Font ; Font ; font +dt ; Fra ; Fraction ; fra +dt ; Init ; Initial ; init +dt ; Iso ; Isolated ; iso +dt ; Med ; Medial ; med +dt ; Nar ; Narrow ; nar +dt ; Nb ; Nobreak ; nb +dt ; None ; None ; none +dt ; Sml ; Small ; sml +dt ; Sqr ; Square ; sqr +dt ; Sub ; Sub ; sub +dt ; Sup ; Super ; sup +dt ; Vert ; Vertical ; vert +dt ; Wide ; Wide ; wide + +# Default_Ignorable_Code_Point (DI) + +DI ; N ; No ; F ; False +DI ; Y ; Yes ; T ; True + +# Deprecated (Dep) + +Dep; N ; No ; F ; False +Dep; Y ; Yes ; T ; True + +# Diacritic (Dia) + +Dia; N ; No ; F ; False +Dia; Y ; Yes ; T ; True + +# East_Asian_Width (ea) + +ea ; A ; Ambiguous +ea ; F ; Fullwidth +ea ; H ; Halfwidth +ea ; N ; Neutral +ea ; Na ; Narrow +ea ; W ; Wide + +# Emoji (Emoji) + +Emoji; N ; No ; F ; False +Emoji; Y ; Yes ; T ; True + +# Emoji_Component (EComp) + +EComp; N ; No ; F ; False +EComp; Y ; Yes ; T ; True + +# Emoji_Modifier (EMod) + +EMod; N ; No ; F ; False +EMod; Y ; Yes ; T ; True + +# Emoji_Modifier_Base (EBase) + +EBase; N ; No ; F ; False +EBase; Y ; Yes ; T ; True + +# Emoji_Presentation (EPres) + +EPres; N ; No ; F ; False +EPres; Y ; Yes ; T ; True + +# Equivalent_Unified_Ideograph (EqUIdeo) + +# @missing: 0000..10FFFF; Equivalent_Unified_Ideograph; + +# Expands_On_NFC (XO_NFC) + +XO_NFC; N ; No ; F ; False +XO_NFC; Y ; Yes ; T ; True + +# Expands_On_NFD (XO_NFD) + +XO_NFD; N ; No ; F ; False +XO_NFD; Y ; Yes ; T ; True + +# Expands_On_NFKC (XO_NFKC) + +XO_NFKC; N ; No ; F ; False +XO_NFKC; Y ; Yes ; T ; True + +# Expands_On_NFKD (XO_NFKD) + +XO_NFKD; N ; No ; F ; False +XO_NFKD; Y ; Yes ; T ; True + +# Extended_Pictographic (ExtPict) + +ExtPict; N ; No ; F ; False +ExtPict; Y ; Yes ; T ; True + +# Extender (Ext) + +Ext; N ; No ; F ; False +Ext; Y ; Yes ; T ; True + +# FC_NFKC_Closure (FC_NFKC) + +# @missing: 0000..10FFFF; FC_NFKC_Closure; + +# Full_Composition_Exclusion (Comp_Ex) + +Comp_Ex; N ; No ; F ; False +Comp_Ex; Y ; Yes ; T ; True + +# General_Category (gc) + +gc ; C ; Other # Cc | Cf | Cn | Co | Cs +gc ; Cc ; Control ; cntrl +gc ; Cf ; Format +gc ; Cn ; Unassigned +gc ; Co ; Private_Use +gc ; Cs ; Surrogate +gc ; L ; Letter # Ll | Lm | Lo | Lt | Lu +gc ; LC ; Cased_Letter # Ll | Lt | Lu +gc ; Ll ; Lowercase_Letter +gc ; Lm ; Modifier_Letter +gc ; Lo ; Other_Letter +gc ; Lt ; Titlecase_Letter +gc ; Lu ; Uppercase_Letter +gc ; M ; Mark ; Combining_Mark # Mc | Me | Mn +gc ; Mc ; Spacing_Mark +gc ; Me ; Enclosing_Mark +gc ; Mn ; Nonspacing_Mark +gc ; N ; Number # Nd | Nl | No +gc ; Nd ; Decimal_Number ; digit +gc ; Nl ; Letter_Number +gc ; No ; Other_Number +gc ; P ; Punctuation ; punct # Pc | Pd | Pe | Pf | Pi | Po | Ps +gc ; Pc ; Connector_Punctuation +gc ; Pd ; Dash_Punctuation +gc ; Pe ; Close_Punctuation +gc ; Pf ; Final_Punctuation +gc ; Pi ; Initial_Punctuation +gc ; Po ; Other_Punctuation +gc ; Ps ; Open_Punctuation +gc ; S ; Symbol # Sc | Sk | Sm | So +gc ; Sc ; Currency_Symbol +gc ; Sk ; Modifier_Symbol +gc ; Sm ; Math_Symbol +gc ; So ; Other_Symbol +gc ; Z ; Separator # Zl | Zp | Zs +gc ; Zl ; Line_Separator +gc ; Zp ; Paragraph_Separator +gc ; Zs ; Space_Separator +# @missing: 0000..10FFFF; General_Category; Unassigned + +# Grapheme_Base (Gr_Base) + +Gr_Base; N ; No ; F ; False +Gr_Base; Y ; Yes ; T ; True + +# Grapheme_Cluster_Break (GCB) + +GCB; CN ; Control +GCB; CR ; CR +GCB; EB ; E_Base +GCB; EBG ; E_Base_GAZ +GCB; EM ; E_Modifier +GCB; EX ; Extend +GCB; GAZ ; Glue_After_Zwj +GCB; L ; L +GCB; LF ; LF +GCB; LV ; LV +GCB; LVT ; LVT +GCB; PP ; Prepend +GCB; RI ; Regional_Indicator +GCB; SM ; SpacingMark +GCB; T ; T +GCB; V ; V +GCB; XX ; Other +GCB; ZWJ ; ZWJ + +# Grapheme_Extend (Gr_Ext) + +Gr_Ext; N ; No ; F ; False +Gr_Ext; Y ; Yes ; T ; True + +# Grapheme_Link (Gr_Link) + +Gr_Link; N ; No ; F ; False +Gr_Link; Y ; Yes ; T ; True + +# Hangul_Syllable_Type (hst) + +hst; L ; Leading_Jamo +hst; LV ; LV_Syllable +hst; LVT ; LVT_Syllable +hst; NA ; Not_Applicable +hst; T ; Trailing_Jamo +hst; V ; Vowel_Jamo + +# Hex_Digit (Hex) + +Hex; N ; No ; F ; False +Hex; Y ; Yes ; T ; True + +# Hyphen (Hyphen) + +Hyphen; N ; No ; F ; False +Hyphen; Y ; Yes ; T ; True + +# IDS_Binary_Operator (IDSB) + +IDSB; N ; No ; F ; False +IDSB; Y ; Yes ; T ; True + +# IDS_Trinary_Operator (IDST) + +IDST; N ; No ; F ; False +IDST; Y ; Yes ; T ; True + +# ID_Continue (IDC) + +IDC; N ; No ; F ; False +IDC; Y ; Yes ; T ; True + +# ID_Start (IDS) + +IDS; N ; No ; F ; False +IDS; Y ; Yes ; T ; True + +# ISO_Comment (isc) + +# @missing: 0000..10FFFF; ISO_Comment; + +# Ideographic (Ideo) + +Ideo; N ; No ; F ; False +Ideo; Y ; Yes ; T ; True + +# Indic_Positional_Category (InPC) + +InPC; Bottom ; Bottom +InPC; Bottom_And_Left ; Bottom_And_Left +InPC; Bottom_And_Right ; Bottom_And_Right +InPC; Left ; Left +InPC; Left_And_Right ; Left_And_Right +InPC; NA ; NA +InPC; Overstruck ; Overstruck +InPC; Right ; Right +InPC; Top ; Top +InPC; Top_And_Bottom ; Top_And_Bottom +InPC; Top_And_Bottom_And_Left ; Top_And_Bottom_And_Left +InPC; Top_And_Bottom_And_Right ; Top_And_Bottom_And_Right +InPC; Top_And_Left ; Top_And_Left +InPC; Top_And_Left_And_Right ; Top_And_Left_And_Right +InPC; Top_And_Right ; Top_And_Right +InPC; Visual_Order_Left ; Visual_Order_Left + +# Indic_Syllabic_Category (InSC) + +InSC; Avagraha ; Avagraha +InSC; Bindu ; Bindu +InSC; Brahmi_Joining_Number ; Brahmi_Joining_Number +InSC; Cantillation_Mark ; Cantillation_Mark +InSC; Consonant ; Consonant +InSC; Consonant_Dead ; Consonant_Dead +InSC; Consonant_Final ; Consonant_Final +InSC; Consonant_Head_Letter ; Consonant_Head_Letter +InSC; Consonant_Initial_Postfixed ; Consonant_Initial_Postfixed +InSC; Consonant_Killer ; Consonant_Killer +InSC; Consonant_Medial ; Consonant_Medial +InSC; Consonant_Placeholder ; Consonant_Placeholder +InSC; Consonant_Preceding_Repha ; Consonant_Preceding_Repha +InSC; Consonant_Prefixed ; Consonant_Prefixed +InSC; Consonant_Subjoined ; Consonant_Subjoined +InSC; Consonant_Succeeding_Repha ; Consonant_Succeeding_Repha +InSC; Consonant_With_Stacker ; Consonant_With_Stacker +InSC; Gemination_Mark ; Gemination_Mark +InSC; Invisible_Stacker ; Invisible_Stacker +InSC; Joiner ; Joiner +InSC; Modifying_Letter ; Modifying_Letter +InSC; Non_Joiner ; Non_Joiner +InSC; Nukta ; Nukta +InSC; Number ; Number +InSC; Number_Joiner ; Number_Joiner +InSC; Other ; Other +InSC; Pure_Killer ; Pure_Killer +InSC; Register_Shifter ; Register_Shifter +InSC; Syllable_Modifier ; Syllable_Modifier +InSC; Tone_Letter ; Tone_Letter +InSC; Tone_Mark ; Tone_Mark +InSC; Virama ; Virama +InSC; Visarga ; Visarga +InSC; Vowel ; Vowel +InSC; Vowel_Dependent ; Vowel_Dependent +InSC; Vowel_Independent ; Vowel_Independent + +# Jamo_Short_Name (JSN) + +JSN; A ; A +JSN; AE ; AE +JSN; B ; B +JSN; BB ; BB +JSN; BS ; BS +JSN; C ; C +JSN; D ; D +JSN; DD ; DD +JSN; E ; E +JSN; EO ; EO +JSN; EU ; EU +JSN; G ; G +JSN; GG ; GG +JSN; GS ; GS +JSN; H ; H +JSN; I ; I +JSN; J ; J +JSN; JJ ; JJ +JSN; K ; K +JSN; L ; L +JSN; LB ; LB +JSN; LG ; LG +JSN; LH ; LH +JSN; LM ; LM +JSN; LP ; LP +JSN; LS ; LS +JSN; LT ; LT +JSN; M ; M +JSN; N ; N +JSN; NG ; NG +JSN; NH ; NH +JSN; NJ ; NJ +JSN; O ; O +JSN; OE ; OE +JSN; P ; P +JSN; R ; R +JSN; S ; S +JSN; SS ; SS +JSN; T ; T +JSN; U ; U +JSN; WA ; WA +JSN; WAE ; WAE +JSN; WE ; WE +JSN; WEO ; WEO +JSN; WI ; WI +JSN; YA ; YA +JSN; YAE ; YAE +JSN; YE ; YE +JSN; YEO ; YEO +JSN; YI ; YI +JSN; YO ; YO +JSN; YU ; YU +# @missing: 0000..10FFFF; Jamo_Short_Name; + +# Join_Control (Join_C) + +Join_C; N ; No ; F ; False +Join_C; Y ; Yes ; T ; True + +# Joining_Group (jg) + +jg ; African_Feh ; African_Feh +jg ; African_Noon ; African_Noon +jg ; African_Qaf ; African_Qaf +jg ; Ain ; Ain +jg ; Alaph ; Alaph +jg ; Alef ; Alef +jg ; Beh ; Beh +jg ; Beth ; Beth +jg ; Burushaski_Yeh_Barree ; Burushaski_Yeh_Barree +jg ; Dal ; Dal +jg ; Dalath_Rish ; Dalath_Rish +jg ; E ; E +jg ; Farsi_Yeh ; Farsi_Yeh +jg ; Fe ; Fe +jg ; Feh ; Feh +jg ; Final_Semkath ; Final_Semkath +jg ; Gaf ; Gaf +jg ; Gamal ; Gamal +jg ; Hah ; Hah +jg ; Hanifi_Rohingya_Kinna_Ya ; Hanifi_Rohingya_Kinna_Ya +jg ; Hanifi_Rohingya_Pa ; Hanifi_Rohingya_Pa +jg ; He ; He +jg ; Heh ; Heh +jg ; Heh_Goal ; Heh_Goal +jg ; Heth ; Heth +jg ; Kaf ; Kaf +jg ; Kaph ; Kaph +jg ; Khaph ; Khaph +jg ; Knotted_Heh ; Knotted_Heh +jg ; Lam ; Lam +jg ; Lamadh ; Lamadh +jg ; Malayalam_Bha ; Malayalam_Bha +jg ; Malayalam_Ja ; Malayalam_Ja +jg ; Malayalam_Lla ; Malayalam_Lla +jg ; Malayalam_Llla ; Malayalam_Llla +jg ; Malayalam_Nga ; Malayalam_Nga +jg ; Malayalam_Nna ; Malayalam_Nna +jg ; Malayalam_Nnna ; Malayalam_Nnna +jg ; Malayalam_Nya ; Malayalam_Nya +jg ; Malayalam_Ra ; Malayalam_Ra +jg ; Malayalam_Ssa ; Malayalam_Ssa +jg ; Malayalam_Tta ; Malayalam_Tta +jg ; Manichaean_Aleph ; Manichaean_Aleph +jg ; Manichaean_Ayin ; Manichaean_Ayin +jg ; Manichaean_Beth ; Manichaean_Beth +jg ; Manichaean_Daleth ; Manichaean_Daleth +jg ; Manichaean_Dhamedh ; Manichaean_Dhamedh +jg ; Manichaean_Five ; Manichaean_Five +jg ; Manichaean_Gimel ; Manichaean_Gimel +jg ; Manichaean_Heth ; Manichaean_Heth +jg ; Manichaean_Hundred ; Manichaean_Hundred +jg ; Manichaean_Kaph ; Manichaean_Kaph +jg ; Manichaean_Lamedh ; Manichaean_Lamedh +jg ; Manichaean_Mem ; Manichaean_Mem +jg ; Manichaean_Nun ; Manichaean_Nun +jg ; Manichaean_One ; Manichaean_One +jg ; Manichaean_Pe ; Manichaean_Pe +jg ; Manichaean_Qoph ; Manichaean_Qoph +jg ; Manichaean_Resh ; Manichaean_Resh +jg ; Manichaean_Sadhe ; Manichaean_Sadhe +jg ; Manichaean_Samekh ; Manichaean_Samekh +jg ; Manichaean_Taw ; Manichaean_Taw +jg ; Manichaean_Ten ; Manichaean_Ten +jg ; Manichaean_Teth ; Manichaean_Teth +jg ; Manichaean_Thamedh ; Manichaean_Thamedh +jg ; Manichaean_Twenty ; Manichaean_Twenty +jg ; Manichaean_Waw ; Manichaean_Waw +jg ; Manichaean_Yodh ; Manichaean_Yodh +jg ; Manichaean_Zayin ; Manichaean_Zayin +jg ; Meem ; Meem +jg ; Mim ; Mim +jg ; No_Joining_Group ; No_Joining_Group +jg ; Noon ; Noon +jg ; Nun ; Nun +jg ; Nya ; Nya +jg ; Pe ; Pe +jg ; Qaf ; Qaf +jg ; Qaph ; Qaph +jg ; Reh ; Reh +jg ; Reversed_Pe ; Reversed_Pe +jg ; Rohingya_Yeh ; Rohingya_Yeh +jg ; Sad ; Sad +jg ; Sadhe ; Sadhe +jg ; Seen ; Seen +jg ; Semkath ; Semkath +jg ; Shin ; Shin +jg ; Straight_Waw ; Straight_Waw +jg ; Swash_Kaf ; Swash_Kaf +jg ; Syriac_Waw ; Syriac_Waw +jg ; Tah ; Tah +jg ; Taw ; Taw +jg ; Teh_Marbuta ; Teh_Marbuta +jg ; Teh_Marbuta_Goal ; Hamza_On_Heh_Goal +jg ; Teth ; Teth +jg ; Thin_Yeh ; Thin_Yeh +jg ; Vertical_Tail ; Vertical_Tail +jg ; Waw ; Waw +jg ; Yeh ; Yeh +jg ; Yeh_Barree ; Yeh_Barree +jg ; Yeh_With_Tail ; Yeh_With_Tail +jg ; Yudh ; Yudh +jg ; Yudh_He ; Yudh_He +jg ; Zain ; Zain +jg ; Zhain ; Zhain + +# Joining_Type (jt) + +jt ; C ; Join_Causing +jt ; D ; Dual_Joining +jt ; L ; Left_Joining +jt ; R ; Right_Joining +jt ; T ; Transparent +jt ; U ; Non_Joining + +# Line_Break (lb) + +lb ; AI ; Ambiguous +lb ; AL ; Alphabetic +lb ; B2 ; Break_Both +lb ; BA ; Break_After +lb ; BB ; Break_Before +lb ; BK ; Mandatory_Break +lb ; CB ; Contingent_Break +lb ; CJ ; Conditional_Japanese_Starter +lb ; CL ; Close_Punctuation +lb ; CM ; Combining_Mark +lb ; CP ; Close_Parenthesis +lb ; CR ; Carriage_Return +lb ; EB ; E_Base +lb ; EM ; E_Modifier +lb ; EX ; Exclamation +lb ; GL ; Glue +lb ; H2 ; H2 +lb ; H3 ; H3 +lb ; HL ; Hebrew_Letter +lb ; HY ; Hyphen +lb ; ID ; Ideographic +lb ; IN ; Inseparable ; Inseperable +lb ; IS ; Infix_Numeric +lb ; JL ; JL +lb ; JT ; JT +lb ; JV ; JV +lb ; LF ; Line_Feed +lb ; NL ; Next_Line +lb ; NS ; Nonstarter +lb ; NU ; Numeric +lb ; OP ; Open_Punctuation +lb ; PO ; Postfix_Numeric +lb ; PR ; Prefix_Numeric +lb ; QU ; Quotation +lb ; RI ; Regional_Indicator +lb ; SA ; Complex_Context +lb ; SG ; Surrogate +lb ; SP ; Space +lb ; SY ; Break_Symbols +lb ; WJ ; Word_Joiner +lb ; XX ; Unknown +lb ; ZW ; ZWSpace +lb ; ZWJ ; ZWJ + +# Logical_Order_Exception (LOE) + +LOE; N ; No ; F ; False +LOE; Y ; Yes ; T ; True + +# Lowercase (Lower) + +Lower; N ; No ; F ; False +Lower; Y ; Yes ; T ; True + +# Lowercase_Mapping (lc) + +# @missing: 0000..10FFFF; Lowercase_Mapping; + +# Math (Math) + +Math; N ; No ; F ; False +Math; Y ; Yes ; T ; True + +# NFC_Quick_Check (NFC_QC) + +NFC_QC; M ; Maybe +NFC_QC; N ; No +NFC_QC; Y ; Yes + +# NFD_Quick_Check (NFD_QC) + +NFD_QC; N ; No +NFD_QC; Y ; Yes + +# NFKC_Casefold (NFKC_CF) + +# @missing: 0000..10FFFF; NFKC_Casefold; + +# NFKC_Quick_Check (NFKC_QC) + +NFKC_QC; M ; Maybe +NFKC_QC; N ; No +NFKC_QC; Y ; Yes + +# NFKD_Quick_Check (NFKD_QC) + +NFKD_QC; N ; No +NFKD_QC; Y ; Yes + +# Name (na) + +# @missing: 0000..10FFFF; Name; + +# Name_Alias (Name_Alias) + +# @missing: 0000..10FFFF; Name_Alias; + +# Noncharacter_Code_Point (NChar) + +NChar; N ; No ; F ; False +NChar; Y ; Yes ; T ; True + +# Numeric_Type (nt) + +nt ; De ; Decimal +nt ; Di ; Digit +nt ; None ; None +nt ; Nu ; Numeric + +# Numeric_Value (nv) + +# @missing: 0000..10FFFF; Numeric_Value; NaN + +# Other_Alphabetic (OAlpha) + +OAlpha; N ; No ; F ; False +OAlpha; Y ; Yes ; T ; True + +# Other_Default_Ignorable_Code_Point (ODI) + +ODI; N ; No ; F ; False +ODI; Y ; Yes ; T ; True + +# Other_Grapheme_Extend (OGr_Ext) + +OGr_Ext; N ; No ; F ; False +OGr_Ext; Y ; Yes ; T ; True + +# Other_ID_Continue (OIDC) + +OIDC; N ; No ; F ; False +OIDC; Y ; Yes ; T ; True + +# Other_ID_Start (OIDS) + +OIDS; N ; No ; F ; False +OIDS; Y ; Yes ; T ; True + +# Other_Lowercase (OLower) + +OLower; N ; No ; F ; False +OLower; Y ; Yes ; T ; True + +# Other_Math (OMath) + +OMath; N ; No ; F ; False +OMath; Y ; Yes ; T ; True + +# Other_Uppercase (OUpper) + +OUpper; N ; No ; F ; False +OUpper; Y ; Yes ; T ; True + +# Pattern_Syntax (Pat_Syn) + +Pat_Syn; N ; No ; F ; False +Pat_Syn; Y ; Yes ; T ; True + +# Pattern_White_Space (Pat_WS) + +Pat_WS; N ; No ; F ; False +Pat_WS; Y ; Yes ; T ; True + +# Prepended_Concatenation_Mark (PCM) + +PCM; N ; No ; F ; False +PCM; Y ; Yes ; T ; True + +# Quotation_Mark (QMark) + +QMark; N ; No ; F ; False +QMark; Y ; Yes ; T ; True + +# Radical (Radical) + +Radical; N ; No ; F ; False +Radical; Y ; Yes ; T ; True + +# Regional_Indicator (RI) + +RI ; N ; No ; F ; False +RI ; Y ; Yes ; T ; True + +# Script (sc) + +sc ; Adlm ; Adlam +sc ; Aghb ; Caucasian_Albanian +sc ; Ahom ; Ahom +sc ; Arab ; Arabic +sc ; Armi ; Imperial_Aramaic +sc ; Armn ; Armenian +sc ; Avst ; Avestan +sc ; Bali ; Balinese +sc ; Bamu ; Bamum +sc ; Bass ; Bassa_Vah +sc ; Batk ; Batak +sc ; Beng ; Bengali +sc ; Bhks ; Bhaiksuki +sc ; Bopo ; Bopomofo +sc ; Brah ; Brahmi +sc ; Brai ; Braille +sc ; Bugi ; Buginese +sc ; Buhd ; Buhid +sc ; Cakm ; Chakma +sc ; Cans ; Canadian_Aboriginal +sc ; Cari ; Carian +sc ; Cham ; Cham +sc ; Cher ; Cherokee +sc ; Chrs ; Chorasmian +sc ; Copt ; Coptic ; Qaac +sc ; Cpmn ; Cypro_Minoan +sc ; Cprt ; Cypriot +sc ; Cyrl ; Cyrillic +sc ; Deva ; Devanagari +sc ; Diak ; Dives_Akuru +sc ; Dogr ; Dogra +sc ; Dsrt ; Deseret +sc ; Dupl ; Duployan +sc ; Egyp ; Egyptian_Hieroglyphs +sc ; Elba ; Elbasan +sc ; Elym ; Elymaic +sc ; Ethi ; Ethiopic +sc ; Geor ; Georgian +sc ; Glag ; Glagolitic +sc ; Gong ; Gunjala_Gondi +sc ; Gonm ; Masaram_Gondi +sc ; Goth ; Gothic +sc ; Gran ; Grantha +sc ; Grek ; Greek +sc ; Gujr ; Gujarati +sc ; Guru ; Gurmukhi +sc ; Hang ; Hangul +sc ; Hani ; Han +sc ; Hano ; Hanunoo +sc ; Hatr ; Hatran +sc ; Hebr ; Hebrew +sc ; Hira ; Hiragana +sc ; Hluw ; Anatolian_Hieroglyphs +sc ; Hmng ; Pahawh_Hmong +sc ; Hmnp ; Nyiakeng_Puachue_Hmong +sc ; Hrkt ; Katakana_Or_Hiragana +sc ; Hung ; Old_Hungarian +sc ; Ital ; Old_Italic +sc ; Java ; Javanese +sc ; Kali ; Kayah_Li +sc ; Kana ; Katakana +sc ; Khar ; Kharoshthi +sc ; Khmr ; Khmer +sc ; Khoj ; Khojki +sc ; Kits ; Khitan_Small_Script +sc ; Knda ; Kannada +sc ; Kthi ; Kaithi +sc ; Lana ; Tai_Tham +sc ; Laoo ; Lao +sc ; Latn ; Latin +sc ; Lepc ; Lepcha +sc ; Limb ; Limbu +sc ; Lina ; Linear_A +sc ; Linb ; Linear_B +sc ; Lisu ; Lisu +sc ; Lyci ; Lycian +sc ; Lydi ; Lydian +sc ; Mahj ; Mahajani +sc ; Maka ; Makasar +sc ; Mand ; Mandaic +sc ; Mani ; Manichaean +sc ; Marc ; Marchen +sc ; Medf ; Medefaidrin +sc ; Mend ; Mende_Kikakui +sc ; Merc ; Meroitic_Cursive +sc ; Mero ; Meroitic_Hieroglyphs +sc ; Mlym ; Malayalam +sc ; Modi ; Modi +sc ; Mong ; Mongolian +sc ; Mroo ; Mro +sc ; Mtei ; Meetei_Mayek +sc ; Mult ; Multani +sc ; Mymr ; Myanmar +sc ; Nand ; Nandinagari +sc ; Narb ; Old_North_Arabian +sc ; Nbat ; Nabataean +sc ; Newa ; Newa +sc ; Nkoo ; Nko +sc ; Nshu ; Nushu +sc ; Ogam ; Ogham +sc ; Olck ; Ol_Chiki +sc ; Orkh ; Old_Turkic +sc ; Orya ; Oriya +sc ; Osge ; Osage +sc ; Osma ; Osmanya +sc ; Ougr ; Old_Uyghur +sc ; Palm ; Palmyrene +sc ; Pauc ; Pau_Cin_Hau +sc ; Perm ; Old_Permic +sc ; Phag ; Phags_Pa +sc ; Phli ; Inscriptional_Pahlavi +sc ; Phlp ; Psalter_Pahlavi +sc ; Phnx ; Phoenician +sc ; Plrd ; Miao +sc ; Prti ; Inscriptional_Parthian +sc ; Rjng ; Rejang +sc ; Rohg ; Hanifi_Rohingya +sc ; Runr ; Runic +sc ; Samr ; Samaritan +sc ; Sarb ; Old_South_Arabian +sc ; Saur ; Saurashtra +sc ; Sgnw ; SignWriting +sc ; Shaw ; Shavian +sc ; Shrd ; Sharada +sc ; Sidd ; Siddham +sc ; Sind ; Khudawadi +sc ; Sinh ; Sinhala +sc ; Sogd ; Sogdian +sc ; Sogo ; Old_Sogdian +sc ; Sora ; Sora_Sompeng +sc ; Soyo ; Soyombo +sc ; Sund ; Sundanese +sc ; Sylo ; Syloti_Nagri +sc ; Syrc ; Syriac +sc ; Tagb ; Tagbanwa +sc ; Takr ; Takri +sc ; Tale ; Tai_Le +sc ; Talu ; New_Tai_Lue +sc ; Taml ; Tamil +sc ; Tang ; Tangut +sc ; Tavt ; Tai_Viet +sc ; Telu ; Telugu +sc ; Tfng ; Tifinagh +sc ; Tglg ; Tagalog +sc ; Thaa ; Thaana +sc ; Thai ; Thai +sc ; Tibt ; Tibetan +sc ; Tirh ; Tirhuta +sc ; Tnsa ; Tangsa +sc ; Toto ; Toto +sc ; Ugar ; Ugaritic +sc ; Vaii ; Vai +sc ; Vith ; Vithkuqi +sc ; Wara ; Warang_Citi +sc ; Wcho ; Wancho +sc ; Xpeo ; Old_Persian +sc ; Xsux ; Cuneiform +sc ; Yezi ; Yezidi +sc ; Yiii ; Yi +sc ; Zanb ; Zanabazar_Square +sc ; Zinh ; Inherited ; Qaai +sc ; Zyyy ; Common +sc ; Zzzz ; Unknown + +# Script_Extensions (scx) + +# @missing: 0000..10FFFF; Script_Extensions;